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 - 仅在组件卸载时使用效果,而不是在依赖项更新时使用的主要内容,如果未能解决你的问题,请参考以下文章

react hook介绍

react父子组件生命周期执行顺序

React Hook的使用

如何写自定义 React Hook?

React Hook 功能组件防止重新渲染

hook 的渲染,你了解吗