reactjs 有条件地调用React挂接

wooyq4lh  于 2022-12-18  发布在  React
关注(0)|答案(3)|浏览(129)

从react的官方文档中我们知道“React依赖于钩子被调用的顺序”,那么如果我想有条件地调用它,为钩子“保留”一个位置有什么错吗?

function Component({flag, depA, depB}) {

  if (flag) {
    // just "reserving a spot"
    useEffect(() => {}, [null, null])
  } else {
    useEffect(() => {
      // ... actual hook
    }, [depA, depB])
  }

  return <></>
}

如果这个方法有效,那么它是否也适用于useCallbackuseLayoutEffectuseMemouseImperativeHandle
我已经测试了所有这些,在更复杂的环境中,即使短绒抱怨,它似乎也能工作。
PS:如果它看起来像这样有点没用,那是因为最终目标是让钩子的主要部分懒洋洋地加载import(),在导入被触发和解析之前,只需要为钩子保留位置。

uelo1irk

uelo1irk1#

我今天刚刚还在想这个问题,我认为虽然它“打破了规则”,但React无法区分两者之间的区别。
因此,虽然它违反了规则,但如果你有足够好的理由,了解风险,那么“规则”只是教条。
React基本上通过计算调用次数来知道哪个是useEffect钩子。有条件地调用useEffect是不好的,特别是因为useEffect被调用的次数不能改变。
您的示例是有条件的,但React无法检测到它,因为在这两种情况下都只调用了一次。
然而,你提到的例子似乎不需要这样做。有很好的理由用“正常”的方式做事,因为正如你从其他评论者那里看到的,它会引起混乱和惊讶,而我们不喜欢惊讶=)
如果您正在延迟加载某些功能,那么只要让useEffect钩子在它 * 准备好 * 时调用该函数即可。

5us2dqdw

5us2dqdw2#

你不能有条件地调用useEffect,因为这违反了钩子的规则,你可以做以下操作:

useEffect(() => {
    if (flag) {
      console.log("do something");
    } else {
      console.log("do something else");
    }
  }, [depA, depB]);
xqkwcwgp

xqkwcwgp3#

我的解决方案是这样的,它适用于所有的钩子,但是最好在必要的时候使用它,因为它可能会引起混乱和惊讶

const ConditionalEffect1 = () => {
  useEffect(() => {}, [])
  return null
}

const ConditionalEffect2 = ({depA, depB}) => {
  useEffect(() => {}, [depA, depB])
  return null
}

const Component = ({ flag, depA, depB }) => {
  return flag 
          ? <ConditionalEffect1 /> 
          : <ConditionalEffect2 depA={depA} depB={depB} />
}

相关问题