停止在挂载上运行 useEffect
Posted
技术标签:
【中文标题】停止在挂载上运行 useEffect【英文标题】:Stop useEffect from running on mount 【发布时间】: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]);
【问题讨论】:
【参考方案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]);
;
深入了解uses of useEffect
【讨论】:
我相信第二个示例存在错误,即“第一次渲染”示例。而不是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。
【讨论】:
以上是关于停止在挂载上运行 useEffect的主要内容,如果未能解决你的问题,请参考以下文章