一、useState + useReducer
const ReactModel = ()=>{const [n,setN] = useState(1)const onClick = ()=>{setN(n+1)}return <div onClick={onClick}>{n}</div>}
const reducer = (state,action)=>{switch (action.type){case 'setN':{return {...state,n: action.n}}}}const ReactModel = ()=>{const [state,dispatch] = useReducer(reducer,initialState)const onClick = ()=>{dispatch({type:'setN',n:state.n+1})}return <div onClick={onClick}>{n}</div>}
二、useEffect + useLayoutEffect
const ReactModel = ()=>{useEffect(()=>{console.log(1)return ()=>{console.log(2)}})}
const ReactModel = ()=>{useEffectLayout(()=>{console.log(1)return ()=>{console.log(2)}})}
三、memo + useMemo/useCallback
const ReactModel = ()=>{const [n,setN] = useState(1)const onClick = useMemo(()=>{return ()=>{console.log(n)}},[n])return <ReactModel2 onClick={onClick} n={n} />}const ReactModel2 = React.memo((props)=>{return <div onClick={props.onClick}>{props.n}</div>})
const ReactModel = ()=>{const [n,setN] = useState(1)const onClick = useCallback(()=>{console.log(n)},[n])return <div onClick={onClick}>{n}</div>}
四、useRef、forwardRef、useImperativeHandle
const ReactModel = ()=>{const nRef = useRef(1)const onClick = ()=>{console.log(nRef.current)nRef.current++}return <div onClick={onClick}>按钮<div>}
const ReactModel = ()=>{const buttonRef = useRef(null)return <Button ref={button}>按钮</Button>}const Button = React.forwardRef((props,ref)=>{return <button ref={ref} {...props}>})
const Button = React.forwardRef((props,ref)=>{const realButton = createRef(null)useImperativeHandle(ref,()=>({x: ()=>{realButton.current.remove()}}))})// 应该叫 setRef
useRef
- 目的
- 如果你需要一个值,在组件不断 render 时保持不变
- 初始化:const count = useRef(0)
- 读取:count.current
- 为什么需要 current?
- 为了保证两次 useRef 是同一个值
- 延伸
- 看看 Vue3 的 ref
- 初始化 const count = ref(0)
- 读取 count.value
- 不同点:当 count.value 变化时,Vue3 会自动 render
五、自定义 Hooks
封装自定义操作
const useList = ()=>{const [list,setList] = useState(null)useEffect(()=>{ajax('/list').then(list=>{setList(list)})},[])return {list,setList}}
「@浪里淘沙的小法师」
