Reactjs 停止在挂载上运行useEffect

Reactjs 停止在挂载上运行useEffect,reactjs,react-redux,react-hooks,use-effect,Reactjs,React Redux,React Hooks,Use Effect,我只想在依赖项列表更改时运行useEffect,它也会在每次装入组件时运行,有没有办法不在装入时启动 如果出现某些值,可以告诉React to skip应用效果 在重新渲染之间没有更改 我最初认为这意味着它不应该在后续的挂载上重新渲染,但是 我在母版“页面”(react router)中显示一个记录列表,用户可以选择一个记录并转到详细信息页面,然后返回母版页-因此在该场景中,母版列表组件完全卸载/装载。每次我加载“母版页”时,我都会看到正在获取的数据,我只希望在其中一个依赖项更改时发生这种情况;

我只想在依赖项列表更改时运行useEffect,它也会在每次装入组件时运行,有没有办法不在装入时启动

如果出现某些值,可以告诉React to skip应用效果 在重新渲染之间没有更改

我最初认为这意味着它不应该在后续的挂载上重新渲染,但是

我在母版“页面”(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]);

您无法对其进行开箱即用的配置

但是,常见的模式是使用一些
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 = false;
    } else {
      console.log("fetching");
      dispatch(fetchData(filters));
    }
  }, [dispatch, filters]);
};

如果您有多个
useffect
,以防止在开始时运行,则可以执行以下操作:


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;
};

导出默认函数App(){
const mountedRef=useMountedRef();
const[isLoggedIn,setLoggedIn]=React.useState(false);
const[anotherOne,setAnotherOne]=React.useState(false);
React.useffect(()=>{
if(mountedRef.current){
console.log(“已触发”,isLoggedIn);
}
},[isLoggedIn]);
React.useffect(()=>{
if(mountedRef.current){
console.log(“已触发”,另一个);
}
},[另一个];
React.useffect(()=>{
if(mountedRef.current){
console.log(“已触发”,isLoggedIn,另一个);
}
},[另一个,伊斯洛格丁];
返回(
setLoggedIn(true)}>Login
);
}
常量useMountedRef=()=>{
const mountedRef=React.useRef(false);
React.useffect(()=>{
设置超时(()=>{
mountedRef.current=true;
});
}, []);
返回安装的REF;
};
演示:

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