如何避免在每次渲染时触发useEffect?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何避免在每次渲染时触发useEffect?相关的知识,希望对你有一定的参考价值。
我正在创建一个自定义钩子,它接受一个对象,然后调用useEffect
。该对象可以包含内联函数。
const stuff = useValidation(
fields:
username: /* more nested objects */
,
onSubmit: () => alert('submitted'),
);
钩子实现看起来像这样:
function useValidation(config)
const [state, dispatch] = useReducer(validationReducer);
useEffect(() =>
validateFields(config.fields, state);
, [config.fields, state]);
还有更多(here's the actual implementation),但这些是相关的部分。
当我内联创建对象时,useEffect
连续运行。发生这种情况是因为React使用引用相等(不是深度相等)来检查内容是否已更改。
我可以通过在useMemo
中包装我的配置来“修复”这个,或者将它移到render方法之外。这两者对开发人员的体验都非常糟糕。
我尝试了Kent C. Dodds的use-deep-compare-effect
库,但由于我在配置中允许使用内联箭头功能,因此它不起作用。
我希望能够让用户输入内联对象,让我以某种方式处理任何更改。
我怎么解决这个问题?
答案
在我看来,每次渲染都会调用useEffect
,因为传递给useValidation
的配置每次都是动态创建的。我的建议是把它放在你使用useValidation
的组件或useValidation
本身的某个地方,如下所示:
function useValidation(config)
const [storedConfig, setStoredConfig] = useState(config);
const [state, dispatch] = useReducer(validationReducer);
useEffect(() =>
validateFields(config.fields, state);
, [storedConfig.fields, state]);
如果配置是可更改的,那么你应该将它存储在钩子之外,无论哪种方式确保配置不是每个渲染的新对象。
另一答案
看起来它只是代码中的语法错误。
你的功能应该是这样的
function useValidation(config)
const [state, dispatch] = useReducer(validationReducer);
useEffect(() =>
validateFields(config.fields, state);
, [config.fields, state])
以上是关于如何避免在每次渲染时触发useEffect?的主要内容,如果未能解决你的问题,请参考以下文章