简体   繁体   English

如何避免在每次渲染时触发 useEffect?

[英]How to avoid triggering useEffect on every render?

I am creating a custom hook that accepts an object and in turn calls useEffect .我正在创建一个接受对象并依次调用useEffect的自定义挂钩。 The object can contain inline functions.该对象可以包含内联函数。

const stuff = useValidation({
  fields: {
    username: { /* more nested objects */ }
  },
  onSubmit: () => alert('submitted'),
});

The hook implementation looks like this:钩子实现如下所示:

function useValidation(config) {
  const [state, dispatch] = useReducer(validationReducer);
  useEffect(() => {
    validateFields(config.fields, state);
  }, [config.fields, state]);
}

There's more to it ( here's the actual implementation ), but these are the relevant parts.还有更多(这里是实际的实现),但这些是相关的部分。

When I create the object inline, the useEffect runs continuously.当我内联创建对象时, useEffect连续运行。 This happens because React uses reference equality (not deep equality) to check whether or not stuff has changed.发生这种情况是因为 React 使用引用相等(不是深度相等)来检查内容是否发生了变化。

I can "fix" this by either wrapping my config in useMemo , or move it outside of the render method.我可以通过将我的配置包装在useMemo中或将其移出渲染方法来“修复”此问题。 Both of these are pretty bad for developer experience.这两者对于开发者体验来说都非常糟糕。

I tried Kent C. Dodds' use-deep-compare-effect library, but since I'm allowing inline arrow functions in my config, it doesn't "work".我尝试了 Kent C. Dodds 的use-deep-compare-effect库,但由于我在我的配置中允许内联箭头函数,所以它不起作用。

Preferably, I'd love to be able to let the user input an inline object, and let me deal with any changes somehow.最好,我希望能够让用户输入一个内联对象,并让我以某种方式处理任何更改。

How can I solve this?我该如何解决这个问题?

It seems to me that useEffect is called every render because the config you pass to useValidation is created on the fly every time.在我看来,每次渲染都会调用useEffect ,因为你传递给useValidation的配置每次都是动态创建的。 My suggestion would be to put this in a state somewhere either in your component where you use useValidation or within the useValidation itself like so:我的建议是将其置于使用useValidation的组件中或useValidation本身内的某处状态,如下所示:

function useValidation(config) {
  const [storedConfig, setStoredConfig] = useState(config);
  const [state, dispatch] = useReducer(validationReducer);

  useEffect(() => {
    validateFields(config.fields, state);
  }, [storedConfig.fields, state]);
}

If the config is changeable then you should have it stored outside of the hook, either way make sure the config isn't a new object every render.如果配置是可变的,那么你应该将它存储在钩子之外,无论哪种方式确保配置不是每次渲染的新对象。

According to the documentation you should not put objects or arrays on the array, but the individual attributes inside it, like this:根据文档,您不应将对象或数组放在数组上,而应将其放在其中的各个属性,如下所示:

function useValidation(config) {
  const [state, dispatch] = useReducer(validationReducer);
  useEffect(() => {
    validateFields(config.fields, state);
  }, [config.fields.username, state]);
}

I don't know what your state is, but should be an immutable value such as a string, number, boolean, etc.我不知道你的state是什么,但应该是一个不可变的值,比如字符串、数字、布尔值等。

Same thing with Date objects, they should be casted to String first. Date对象也一样,它们应该首先转换为String

looks like it's only Syntax Error in your code.看起来它只是代码中的语法错误。

your function should look like this你的功能应该是这样的

function useValidation(config) {
 const [state, dispatch] = useReducer(validationReducer);
  useEffect(() => {
    validateFields(config.fields, state);
  }, [config.fields, state])
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 避免 useEffect 在第一次加载时渲染? - avoid useEffect to render at first load? 如何避免useEffect钩子中的setState导致第二次渲染 - How to avoid setState in useEffect hook causing second render React useEffect Hook 不会在具有 [] 依赖项的第一次渲染时触发 - React useEffect Hook not Triggering on First Render with [] Dependencies React useEffect 避免每次更新中的更新回调 - React useEffect avoid update callback in every update 每次渲染后会调用哪个 useEffect? - Which useEffect will be called after every Render? 每次渲染时都将不同的 function 传递给 useEffect? - ReactJS 使用效果 - Different function gets passed to useEffect on every render? - ReactJS useEffect 如何在不使用 useEffect 触发无限循环的情况下实现这一点 - How to implement this without triggering an infinite loop with useEffect 如何避免 useEffect() 竞争条件 - how to avoid useEffect() race condition 如何在 React Native 应用程序中使用 React hook useEffect 每 5 秒渲染一次 setInterval? - How to setInterval for every 5 second render with React hook useEffect in React Native app? 如何修复警告“function — 使 useEffect Hook 的依赖项在每次渲染时都发生变化”? - How to fix warning “function — makes the dependencies of useEffect Hook change on every render”?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM