reactjs 在启用StrictMode的情况下处理useEffect内部的非幂等突变

qf9go6mv  于 2023-03-22  发布在  React
关注(0)|答案(3)|浏览(108)

我正在开发一个组件,我从URL读取查询参数并在useEffect中发布请求,由于严格模式,这将执行两次。请求是非幂等的,处理这种情况的最佳方法是什么?
我在考虑维护一个ref,它包含请求是否被执行,如果请求已经被执行,就不执行它。

j0pj023g

j0pj023g1#

文档建议使用cleanup函数,它不是阻止它触发两次,而是恢复第一次执行的效果,这样看起来就像只运行了一次一样。
例如,

useEffect( () => {
  const dialog = dialogRef.current;
  dialog.showModal();

  // This will run after the first execution and close the modal that was just opened.
  // Then the second execution will re-open it, and it will remain open.
  return () => dialog.close();
}, [] );
bpzcxfmw

bpzcxfmw2#

如果您希望请求在应用程序的每个生命周期中真正只运行一次,则可以跟踪请求是否以顶级变量开始。这听起来太简单了,但它确实满足需求。
www.example.com中也建议使用此方法react.dev

let didInit = false;

function App() {
  useEffect(() => {
    if (!didInit) {
      didInit = true;
      // ✅ Only runs once per app load
      loadDataFromLocalStorage();
      checkAuthToken();
    }
  }, []);
  // ...
}

在OAuth2.0 response_type=code响应处理中处理code查询字符串参数时,我遇到了类似的问题。我想从查询字符串中清除code,但当我的组件作为React 18新的StrictMode行为的一部分重新挂载时,我不会有令牌响应或code查询字符串。因此,第二次安装组件时,它看起来像是一个新的加载,我应该重定向到我的登录页面。
useRef也有类似的效果,但不知何故感觉更古怪,我想是因为它不能保证我的代码在每个页面加载时只运行一次。

7vhp5slm

7vhp5slm3#

我期望的解决方案是使用react ref。它将与组件外部的变量一起工作,但我更喜欢在其内部具有任何特定于组件的逻辑。
请确保立即设置ref,而不是等待请求完成-否则,它将在react开发环境中运行两次。

export const MyComponent = () => {
  const initialRequestPerformed = React.useRef<boolean>(false);

  useEffect(() => {
    if (initialRequestPerformed.current) {
      return;
    }
    initialRequestPerformed.current = true;
    
    // send request
  }, []);

  return <></>
}

相关问题