之前写代码很少使用memo和useCallback优化组件,这里测试了一下,
代码:
//子组件
const Child=memo(props=>{
console.log('子组件render')
return <div>
<h2 onClick={props.add}>list</h2>
{props.list.map(v=><div>{v}</div>)}
</div>
})
//useImmer
import produce from 'immer'
const useImmer=(s)=>{
const [state,_setState]=useState(s)
const setState=(fn)=>_setState(produce(state,fn))
return [state,setState]
}
//父组件
const App=()=>{
console.log('父组件render')
const [state, setState] = useImmer({num:1,list:[1,2,3]})
const setNum=()=>{
setState(draft=>{draft.num+=1})
}
const add=useCallback(()=>{
setState(draft=>{draft.list.push(1)})
},[state.list])
console.log(state)
return <div>
<div onClick={setNum}>num:{state.num}</div>
<Child list={state.list} add={add}/>
</div>
}
子组件使用了memo包括,render前后会对add函数和list进行浅比较,点击seNum,num增加,list和add都没有变,所以子组件没有刷新,复合预期.
点击add子组件列表增加,但是num会回到初始状态变为1,为什么num状态没有被保存,是useCallback使用错误还是immer使用错误?
另外之前公众号有推送文章谈到了useCallback使用,核心意思是hooks组将内的函数尽量都用useCallback包括,这样可以避免组件刷新导致组件内的函数频繁创建销毁,useCallback可以缓存这些方法,当组件刷新时候可以直接使用,是否应该这样使用?
useCallback形成的闭包造成的吧,也和你传入的依赖变量[state.list]。就是说你这个callback的依赖其实并不是只有list变了才更新callback,而是number也是依赖,所以依赖整个state。
所以改写成下面这样就OK: