React Hook - 仅在组件卸载时使用效果,而不是在依赖项更新时使用
Posted
技术标签:
【中文标题】React Hook - 仅在组件卸载时使用效果,而不是在依赖项更新时使用【英文标题】:React Hook - Use effect on component unmount only, not when dependency updates 【发布时间】:2020-02-27 00:24:33 【问题描述】:我正在尝试使用 React Hooks 构建一个输入组件,该组件会命中远程服务器以仅在组件卸载时保存更新的值。
远程服务器调用很昂贵,所以我不想每次输入更新时都访问服务器。
当我在useEffect
中使用清理挂钩时,我需要将输入值包含在效果依赖数组中,这使得远程 API 调用在每次更新输入值时执行。如果我没有在效果依赖数组中包含输入值,则永远不会保存更新的输入值。
这里是一个代码沙箱,它显示了问题并解释了预期的结果:https://codesandbox.io/s/competent-meadow-nzkyv
是否可以使用 React 钩子来完成此任务?我知道它违反了钩子范式的某些部分,但肯定这是一个足够常见的用例,它应该是可能的。
【问题讨论】:
您可以debounce 发送具有较大等待间隔值的值的函数,并在您的钩子中调用该去抖动函数,并将输入值作为依赖项。这样,更新请求就不会在每次击键时都发送到您的后端。确保只声明一次去抖函数。如果可能的话,在你的函数组件之外,或者通过组件内部的useCallback
。
@tiguchi - 我想过这个问题,现在还在考虑。我对使用 debounce 的担心是,如果他们强制组件卸载(即关闭带有表单的模式),则可能无法保存状态。所以,我要么需要一个非常小的等待间隔,要么我仍然需要解决这个问题:(
我认为只有在超时触发API调用之前用户故意重新加载或离开页面时才会出现问题。 React JS 应用程序通常被建模为 SPA,因此即使浏览器 URL 更改也不会导致超时或其他全局状态丢失。但是,您可以创建类似于 API 单例服务的东西,将这些 API 请求排队,以“去抖动”方式处理它们,并确保在当前页面卸载时(通过刷新或离开站点)处理所有剩余的排队请求)
【参考方案1】:
您可以使用ref 来捕获文本的变化值,然后您可以在另一个useEffect
挂钩中引用它来保存文本:
const [text, setText] = useState("");
const textRef = React.useRef(text);
React.useEffect( () =>
textRef.current = text;
, [text])
React.useEffect( () =>
return () => doSomething(textRef.current)
, [])
【讨论】:
感谢您的回复——我也考虑过这种方法。我希望继续使用useState
,因为我确实想根据输入状态的更新重新渲染
这种方法适用于您管理的状态我更新了答案以更明确地显示这一点
我明白了!这是有道理的。谢谢【参考方案2】:
thedude
的做法是对的。稍微调整一下,对于这个特定的用例,input
ref 总是相同的:
function SavedInput()
const inputEl = useRef(null);
React.useEffect(() =>
return () =>
save(inputEl.current.value);
;
, []);
return (
<div>
<input ref=inputEl />
</div>
);
通过这种方式,您可以避免重新渲染,因为您没有设置任何状态。
【讨论】:
以上是关于React Hook - 仅在组件卸载时使用效果,而不是在依赖项更新时使用的主要内容,如果未能解决你的问题,请参考以下文章