关于useEffect和useCallBack踩坑

副作用的操作可以放在useEffect中执行,并且其每次执行都会清除上一次的副作用,副作用一般都为修改DOM, 生成不确定的值等

const Menus = () => {
  const [selectedKey, changeSelectedKey] = useState(['/admin/index'])
  const [menu, setMenu] = useState([])
  const changeSelected = (value: string[]) => {
    changeSelectedKey(value)
  }
  /*
  踩坑--useEffect执行时机和监视state
  1. 在useEffect中可以进行setState,但是不能监视该state,因为本身就是在useEffect中进行渲染的数据
  如果还监视该数据,那么渲染过程中就会重新render, 就会重新执行useEffect,就会继续重新渲染,一直递归死循环
  2. 在useEffect中可以进行赋值操作,但是需要注意的是,如果赋值的数据不是state的话,那么每次更新都会重新执行并赋值
    比如我将menus赋值给menu,那么页面的任何更新都会造成上一次的menu数据被销毁,下一次又会重新创建,因此不能这么干
    也是建议不变的不想被销毁的数据的话,还是存在state中
  3. 关于设置一些值并在页面上进行渲染的问题
    如果设置一个变量,页面上渲染这个变量,没问题,但是如上述说的,每次页面更新都会重新创建这个变量并且重新赋值,所以复杂的变量的话,最好存在state中
    如果撇开这个,就是直接创建了一个变量,页面上用了这个变量,那么该变量展示的就是创建时的赋值,如果想给个初始值并且在useEffect中进行赋值的话,那么是做不到的,或者说可以做到,但是页面上并不会使用该值,因为该变量并不是被监视的数据
  const initMenu: any = (menus: Imenu[]) => {
     return menus.map((item) => {
       if (item.children) {
         return (
           <SubMenu key={item.key} title={item.title}>
             {initMenu(item.children as Imenu[])}
           </SubMenu>
         )
       } else {
         return (
           <Menu.Item key={item.key} icon={<item.icon />}>
             <Link to={item.key}>{item.title}</Link>
           </Menu.Item>
         )
       }
     })
   }
   let menu: any = []
   menu = initMenu(menus)
  */

  /*
  关于useCallBack使用
  并不是所有函数都需要用callBack包裹的,虽然其作用就是记住组件中定义的函数,下次渲染时不会再重新创建
  但是正常情况下这种记住是需要花费代价的,正常情况下的组件中定义的函数,不需要使用useCallBack
  使用其的场景:
    1. 函数很复杂,重新生成确实需要花费很大的代价,比如递归
    2. 该函数要传给子组件
      关于这个需要说明的是,如果不是用callBack的话,那么每次传递给子组件的都是不同的函数
      那么子组件就重新渲染了
  下面定义的这个函数,不知为何提示我使用useCallBack,我测试是因为递归的原因,如果没有递归的话,就完全不需要了
  并且使用callBack定义的函数,如果在useEffect中调用的话,需要将其添加到依赖数组中 
  const initMenu: any = useCallback((menus: Imenu[]) => {
     const init = (menus: Imenu[]) => {
       return menus.map(item => {
          if(item.children) {
            return (
              <SubMenu key={item.key} title={item.title}>
                  {init((item.children as Imenu[]))}
              </SubMenu>
            )
          }else {
            return (
              <Menu.Item key={item.key} icon={<item.icon/>}>
                <Link to={item.key}>{item.title}</Link>
              </Menu.Item>
            )
          }
        })
      }
     return init(menus)
   }, [])
  */
  useEffect(() => {
    // menu = initMenu(menus) 这里给变量赋值,上面说过这样做哪里不对了
    // setMenu(initMenu(menus))
  }, [selectedKey])
  return (
    <Menu
      mode='inline'
      openKeys={selectedKey}
      onOpenChange={changeSelected}
      style={{ width: 256 }}
    >
      {menu}
    </Menu>
  )
}
export default Menus
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值