javascript - 反应:useEffect “悖论”与 eventHandler 道具
问题描述
这个例子有问题。
我有一个Input
组件。这个输入组件有一个onChange
prop 来处理内部的任何数据更改。
应该是这样,如果我更新value
from outside,onChange
则不会触发道具,因为输入组件内部没有任何变化。如果你开始输入,onChange
道具就会被触发,我也可以从外部更新状态。
但是如果满足某些条件(在我的示例中只是一个布尔状态),我想从内部预填充输入字段,因此我必须调用一个onChange
事件,以便应用程序可以从外部更新状态。
问题/悖论是useEffect
检查条件现在需要onChange
prop 作为依赖项,并且由于此 prop 是一种方法,它会在每次渲染时发生变化。这意味着现在输入元素总是在任何更改时重置为 useEffect 的值,因为 useEffect 再次被触发。
如果允许我从 useEffect 依赖项中删除道具,我的问题就不会存在onChange
,但这当然违反了 useEffect 挂钩的规则。
我想到的唯一“解决方案”:
- 我可以将 Input 元素之外的条件移到 App 组件中。这对我的示例有意义,但在实际场景中,每次使用组件时都应该相同,并且我不想每次都从外部重复条件,因为条件也不仅仅是真实的布尔值当然是场景。
- 我可以添加一个额外的状态,是否已经检查了条件,并且仅在尚未触发时触发 useEffect。但这会很快变得非常复杂,如果条件需要在某个时候再次检查等等。等等。
我在不同形状的场景中遇到过这个问题,所以我真的希望得到一个可以应用于一般类似场景的答案。也许我的代码中只是有一个关于如何使用事件处理程序的反模式?
预先感谢您的所有回答^^。
解决方案
我会将 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]);
推荐阅读
- javascript - 无法在 Anchor 内设置 Grommet 图标
- c++ - 如何处理这个循环?
- firebase - 带有firebase的flutter应用程序在热重载时崩溃
- templates - Consul-Termplate - 将变量插入“带秘密”证书调用的语法是什么
- arrays - Powershell:读取主机以选择数组索引
- html - 在 VS Code 中保存时关闭自动关闭的 HTML 标签?
- asynchronous - 如何测量 Julia 中函数的 @async 运行时?
- pact - 使用 SpringRestPactRunner 时出现 NoSuchMethodException
- function - 有人可以帮我把这个函数翻译成 sml 吗?
- javascript - 如何在 appcelerator Titanium 中将 WKWebView 与本地文件一起使用?