hooks组件更新问题?

小木
  • 295

之前写代码很少使用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可以缓存这些方法,当组件刷新时候可以直接使用,是否应该这样使用?

回复
阅读 4.6k
1 个回答
✓ 已被采纳

useCallback形成的闭包造成的吧,也和你传入的依赖变量[state.list]。就是说你这个callback的依赖其实并不是只有list变了才更新callback,而是number也是依赖,所以依赖整个state。

所以改写成下面这样就OK:

const add=useCallback(()=>{
    setState(draft=> { draft.list.push(draft.list.length + 1); })
  },[state])
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏