useState
// 使用
const [n,setN] = React.useState(0)
const [user,setUser] = React.useState({name : 'x',age : x})
const onClick = () =>{
setUser({
...user, // 无法进行局部更新,需要配合 ...进行拷贝
name : 'y'
})
}
const [state , setState] = React.useState(()=>{return initialState})
// 返回初始的state 只能执行一次
const onClick = () =>{
setN(n+1)
setN(n+1) // 无法加2
setN(i => i+1)
setN(n => i+1) // 可以加2
}
在React中 setUser(obj)如果obj 的地址没变,那么React就认为数据没有变化,需要生成一个新的对象
useReducer
四步: 1、创建初始值 initialState
2、创建所有操作reducer(state,action)
3、传给useReducer 得到读和写的API
4、调用写的({type:’操作类型’})
const initial = { n : 0 }
// 主要流程
const reducer = (state , action) =>{
if(action.type === 'add'){
return { n : state.n + action.number }
}else {
throw new Error('unknown')
}
}
function App(){
const [state , dispatch] = React.useReducer(reducer , initial)
const n = state.n // const {n} = state
const onClick = () =>{
dispatch({type : 'add' , number : 1})
return(
<div className="App">
<h1>n: {n}</h1>
<button onClick={onClick}>+1</button>
</div>
)
}
useContext
// 创建上下文
const n = React.createContext(null)
// 圈定作用域
function App(){
const [n,setN] = useState(0)
return(
<n.Provider value={{ n, setN }}>
<div className="App">
<X />
</div>
</n.Provider>
)
}
// 使用上下文
function X() {
const { n, setN } = useContext(n);
return (
<div>
n: {n}
</div>
);
}
useEffect 和 useLayoutEffect
useEffect在浏览器渲染结束后执行,useLayoutEffect在浏览器渲染前执行。虽然useLayoutEffect先执行,但是为了用户体验优先使用useEffect
useEffect(()=>{
console.log("useEffect")
},[]) // 首次渲染
useEffect(()=>{
console.log("useEffect")
},[x]) // 当x发生变化进行渲染
useLayoutEffect(()=>{
console.log("useLayoutEffect")
}) // 所有的都进行渲染
useMemo 和 useCallback
useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数
// 使用React.memo
function Child(props){
console.log("hello")
return(
<div>props.data</div>
)
}
const Child2 = React.memo(Child)
// 使用useMemo,只有在m发生变化才会使用新的
const onClickChild = useMemo(()=>{
return () =>{
console.log(m)
}
},[m])
// 当返回函数时
useMemo(()=> (x)=>consloe.log(x),[m])
// 上下等价
useCallback((x) => consloe.log(x),[m])
useRef
useRef返回一个可变的ref对象,其.current属性初始化为传入的参数
在组件不断render的时候保持不变,当变化时不会自动render,需要自行调用
const count = useRef(0) // 初始化
// current 为了保证对象不变
useEffect(() =>{
count.current += 1
consloe.log(count.current)
})
forwardRef
当一个函数组件需要接受其他组件传来的ref参数,必须要用forwardRef。可以接受一个ref参数
const x = React.forwardRef((props,ref) =>{})
useImperativeHandle
useImperativeHandle让在使用ref时自定义暴露给父组件的实例指。
useImperativeHandle(ref,()=>({
x : ()=>{} // x为暴露给父组件的方法
}))
自定义Hook
一般使用useXXX 开头