感觉自己啥也不会,啊啊啊啊啊啊(发个癫)
受控表单绑定
基本概念
使用React组件的状态控制表单的状态

代码实现
import { useState } from 'react';
function MyForm() {
const [inputValue, setInputValue] = useState("");
return (
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
);
}
获取DOM
使用userRef钩子函数生成一个ref对象,然后绑定到dom标签上,在dom可用时,用current方法获取dom
代码实现
import {useRef} from "react"
function List(){
const inputRef = useRef(null)
const showDom = () => {
console.dir(inputRef.current)
}
return(
<div>
<input type="text" ref={inputRef} />
<button onClick={showDom}>获取DOM</button>
</div>
)
}
export default List
组件通信
组件通信就是组件之间传递数据,根据组件嵌套关系不同,有不同的通信方法。
父子通讯
父传子
在子组件标签上绑定属性,子组件通过props参数接收数据。
代码实现
function Content(props){
console.log(props)
return <div>play Delta Force</div>
}
function List(){
const detail = 'welcome to'
return(
<div>
<Content detail={detail}></Content>
</div>
)
}
export default List
props是一个对象,包含了父组件传递过来的所有数据。

props可以传递任何类型的数据,可以是数字对象,字符串,也可以是对象函数,JSX。但是子组件只能读取props中的数据,并不能直接修改,父组件的数据只能由父组件修改。
<Content
detail={detail}
age={18}
isTrue={false}
list={['vue','react']}
obj={{name: 'ttdr'}}
cd={() => console.log('ttdr')}
child ={<div>this is jsx</div>}
></Content>
这么多类型都可以。
父传子特殊的prop children
当我们把内容嵌套在子组件中,父组件ui自动在名为children的prop的属性中接收该内容。
such as
<Content><div>Star Railway</div></Content>
我们也只需要用{prop.children}在子组件里面渲染
子传父
在子组件中调用父组件中的函数并且传递参数。
import {useRef} from "react"
function Content(props){
const sonMsg = 'this is msg'
return(
<button onClick={() => props.onGetmsg(sonMsg)}>click</button>
)
}
function List(){
const [msg,setMsg] = useState('')
const getMsg =(msg) =>{
console.log(msg)
setMsg(msg)
}
return(
<div>
{msg}
<Content
onGetmsg ={getMsg}
></Content>
</div>
)
}
export default List
兄弟组件通信
借助状态提升机制,通过共同的父组件进行兄弟组件之间的提升
说白了就是子传父再传子。
Context实现跨层通讯
通过createContext方法创建一个上下文对象,顶层组件通过Ctx.Provider组件提供数据,底层通过useContext钩子函数获取使用数据
import {createContext, useContext, useRef} from "react"
const MsgContext = createContext()
function B(){
const message = useContext(MsgContext)
return (
<div>this is b {message}</div>
)
}
function A(){
return(
<>
<div>this is a</div>
<B />
</>
)
}
function List(){
const message ='this is message'
return(
<div>
<MsgContext.Provider value={message}>
this is top
<A />
</MsgContext.Provider>
</div>
)
}
export default List
value就是要传输的值
useEffect
这是一个Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作,入AJAX请求,更改DOM等等
比如说一个模块渲染完毕,就向服务器请求数据。
语法:
useEffect(() => {},[])
第一个参数是函数,称为副作用函数,在函数内部可以放置需要执行的操作
第二个参数是数组,在数字内放置依赖项,不同依赖项会影响第一个参数函数的执行,如果是空数组副作用函数只会在渲染完毕后执行一次
import { useEffect, useState } from 'react'
function App() {
useEffect(() => {
async function loadData() {
// 发送请求...
console.log('组件渲染完毕,只执行一次')
}
loadData()
}, [])
return <div>App</div>
}
如果不是空数组,组件初始渲染执行一次 + 当数组内的依赖项发生变化时执行一次
import { useEffect, useState } from 'react'
function App() {
const [count, setCount] = useState(0)
useEffect(() => {
console.log('count 发生了变化:', count)
document.title = `当前点击了 ${count} 次`
}, [count])
return (
<button onClick={() => setCount(count + 1)}>+1</button>
)
}
清除副作用
在 useEffect 中,如果开启了定时器、订阅了事件或建立了 socket 连接,需要在组件卸载(Unmount)或依赖项变化重新执行副作用前进行清理,防止内存泄漏。
在副作用函数内部 return 一个新的函数,这个函数就是清理函数。
import { useEffect, useState } from 'react'
function Timer() {
useEffect(() => {
const timerId = setInterval(() => {
console.log('定时器执行中')
}, 1000)
return () => {
clearInterval(timerId)
console.log('已清理')
}
}, [])
return <div>Timer Running...</div>
}
function App() {
const [show, setShow] = useState(true)
return (
<div>
{show && <Timer />}
<button onClick={() => setShow(!show)}>切换显示/隐藏</button>
</div>
)
}
自定义 Hook 实现
以use打头的函数,实现逻辑的封装和复用
import { useState } from 'react'
function useToggle() {
const [value, setValue] = useState(true)
const toggle = () => setValue(!value)
return {
value,
toggle
}
}
function App() {
const { value, toggle } = useToggle()
return (
<div>
{value && <div>This is a Div</div>}
<button onClick={toggle}>Toggle</button>
</div>
)
}
注意事项
1.只能在函数组件的最顶层调用
禁止在循环(if/for)、条件判断或嵌套函数中调用 Hook,React 依靠 Hook 调用的顺序来确定每个 state 对应哪个 Hook,打乱顺序会导致数据错乱。
2.只能在 React 函数组件或自定义 Hook 中调用
禁止在普通的 JavaScript 函数中调用 Hook。








