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) // 无法加2setN(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} = stateconst 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.memofunction 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 += 1consloe.log(count.current)})
forwardRef
当一个函数组件需要接受其他组件传来的ref参数,必须要用forwardRef。可以接受一个ref参数
const x = React.forwardRef((props,ref) =>{})
useImperativeHandle
useImperativeHandle让在使用ref时自定义暴露给父组件的实例指。
useImperativeHandle(ref,()=>({x : ()=>{} // x为暴露给父组件的方法}))
自定义Hook
一般使用useXXX 开头
