首页 > 解决方案 > 反应:useEffect “悖论”与 eventHandler 道具

问题描述

这个例子有问题。

我有一个Input组件。这个输入组件有一个onChangeprop 来处理内部的任何数据更改。

应该是这样,如果我更新valuefrom outsideonChange则不会触发道具,因为输入组件内部没有任何变化。如果你开始输入,onChange道具就会被触发,我也可以从外部更新状态。

但是如果满足某些条件(在我的示例中只是一个布尔状态),我想从内部预填充输入字段,因此我必须调用一个onChange事件,以便应用程序可以从外部更新状态。

问题/悖论是useEffect检查条件现在需要onChangeprop 作为依赖项,并且由于此 prop 是一种方法,它会在每次渲染时发生变化。这意味着现在输入元素总是在任何更改时重置为 useEffect 的值,因为 useEffect 再次被触发。

如果允许我从 useEffect 依赖项中删除道具,我的问题就不会存在onChange,但这当然违反了 useEffect 挂钩的规则。

我想到的唯一“解决方案”:

我在不同形状的场景中遇到过这个问题,所以我真的希望得到一个可以应用于一般类似场景的答案。也许我的代码中只是有一个关于如何使用事件处理程序的反模式?

预先感谢您的所有回答^^。

标签: javascriptreactjsreact-hooksuse-effect

解决方案


我会将 if 语句更改为仅在prefillCondition已更改时运行。这意味着您需要知道上次渲染时的值。这样做内联看起来像:

const [prefillCondition, setPrefillCondition] = React.useState(false);
const previous = useRef();
React.useEffect(() => {
  previous.current = prefillCondition;
})
React.useEffect(() => {
  // On the first render, previous.current will be undefined. On every render after that
  // it will tell you what value prefillCondition had on the previous render.
  if (prefillCondition && !previous.current) {
    onChange("value from useEeffff");
  }
}, [onChange, prefillCondition, previous]);

我发现想要记住上一次渲染中的值是很常见的。如果您也这样做,您可能需要考虑将该逻辑提取到自定义挂钩中:

const usePrevious = (value) => {
  const previous = useRef();
  React.useEffect(() => {
    previous.current = value;
  })
  return previous.current;
}

// used like:
const [prefillCondition, setPrefillCondition] = React.useState(false);
const prevPrefillCondition = usePrevious(prefillCondition);
React.useEffect(() => {
  if (prefillCondition && !prevPrefillCondition) {
    onChange("value from useEeffff");
  }
}, [onChange, prefillCondition, prevPrefillCondition]);

推荐阅读