【问题标题】:Stop useEffect from running on mount停止在挂载上运行 useEffect
【发布时间】:2020-04-16 22:40:00
【问题描述】:

我只希望useEffect在我的依赖列表发生变化时运行,每次挂载组件时它也运行,有什么办法在挂载时不触发?

如果某些值,你可以告诉 React 跳过应用效果 重新渲染之间没有变化。

我最初认为这意味着它不应该在后续安装时重新渲染,而是 this question cleared that up.

我在主“页面”(react-router)中显示记录列表,用户可以选择单个记录并转到详细信息页面,然后返回主页面 - 所以主列表组件是在那种情况下完全卸载/安装。每次我加载“母版页”时,我都会看到正在获取的数据,我只希望在其中一个依赖项发生变化时发生这种情况;这些依赖项和数据本身都存储在 Redux 中,因此它们是全局的。

是否可以使 useEffect 或其他挂钩仅在依赖项更改时触发?

const {page, pageSize, search, sorts} = useSelector(getFilters);
const data = useSelector(getData);

useEffect(() => {

  console.log("fetching");
  dispatch(fetchData(page, pageSize, search, sorts));

}, [page, pageSize, search, sorts]);

【问题讨论】:

    标签: reactjs react-redux react-hooks use-effect


    【解决方案1】:

    您不能开箱即用地对其进行配置。

    但是,一个常见的模式是像这样使用一些isMounted 标志:

    // Is Mounted
    const useFetchNotOnMount = () => {
      ...
      const isMounted = useRef(false);
    
      useEffect(() => {
        if (isMounted.current) {
          console.log('fetching');
          dispatch(fetchData(filters));
        } else {
          isMounted.current = true;
        }
      }, [dispatch, filters]);
    };
    
    // Same (Is First Render)
    const useFetchNotOnMount = () => {
      ...
      const isFirstRender = useRef(true);
    
      useEffect(() => {
        if (isFirstRender.current) {
          isFirstRender.current = false;
        } else {
          console.log("fetching");
          dispatch(fetchData(filters));
        }
      }, [dispatch, filters]);
    };
    

    【讨论】:

    • 我相信第二个示例存在错误,即“第一次渲染”示例。而不是isFirstRender = false,它应该是isFirstRender.current = false
    • @GregL 谢谢你是对的
    【解决方案2】:

    如果您有多个useEffect 最初需要阻止运行,您可以执行以下操作:

    
    export default function App() {
      const mountedRef = useMountedRef();
      const [isLoggedIn, setLoggedIn] = React.useState(false);
      const [anotherOne, setAnotherOne] = React.useState(false);
    
      React.useEffect(() => {
        if (mountedRef.current) {
          console.log("triggered", isLoggedIn);
        }
      }, [isLoggedIn]);
    
      React.useEffect(() => {
        if (mountedRef.current) {
          console.log("triggered", anotherOne);
        }
      }, [anotherOne]);
    
      React.useEffect(() => {
        if (mountedRef.current) {
          console.log("triggered", isLoggedIn, anotherOne);
        }
      }, [anotherOne, isLoggedIn]);
    
      return (
        <div>
          <button onClick={() => setLoggedIn(true)}>Login</button>
        </div>
      );
    }
    
    const useMountedRef = () => {
      const mountedRef = React.useRef(false);
    
      React.useEffect(() => {
        setTimeout(() => {
          mountedRef.current = true;
        });
      }, []);
    
      return mountedRef;
    };
    

    演示:https://stackblitz.com/edit/react-eelqp2

    有一点很重要,您必须使用setTimeout 进行合理的延迟,以确保在所有初始 useEffects 之后将 ref 值设置为 true。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      • 2019-10-05
      相关资源
      最近更新 更多