使用React的新效果挂钩,我可以告诉React,如果在重新渲染之间某些值没有更改,则可以跳过应用效果-React文档中的示例:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
但上面的示例在初始渲染时应用效果,并在count
已更改的后续重新渲染时应用效果。如何告诉React跳过初始渲染上的效果?
正如《指南》所述,
效果挂钩useEffect增加了从功能组件执行副作用的能力。它与React类中的componentDidMount、componentDidUpdate和componentWillUnmount的作用相同,但统一为一个API。
在本指南的示例中,仅在初始渲染时,count
应为0:
const [count, setCount] = useState(0);
因此,它将作为componentdiddupdate
工作,并进行额外检查:
useEffect(() => {
if (count)
document.title = `You clicked ${count} times`;
}, [count]);
这就是可以用来代替useffect
的自定义钩子的工作原理:
function useDidUpdateEffect(fn, inputs) {
const didMountRef = useRef(false);
useEffect(() => {
if (didMountRef.current)
return fn();
else
didMountRef.current = true;
}, inputs);
}
建议useRef
而不是setState
的学分转到@Tholle。
这里有一个自定义钩子,它只提供了一个布尔标志来指示当前渲染是否是第一次渲染(当组件被挂载时)。它与其他一些答案大致相同,但您可以在use效应
或渲染函数或组件中的任何其他地方使用标志。也许有人可以提出一个更好的名字。
import { useRef, useEffect } from 'react';
export const useIsMount = () => {
const isMountRef = useRef(true);
useEffect(() => {
isMountRef.current = false;
}, []);
return isMountRef.current;
};
您可以像这样使用它:
import React, { useEffect } from 'react';
import { useIsMount } from './useIsMount';
const MyComponent = () => {
const isMount = useIsMount();
useEffect(() => {
if (isMount) {
console.log('First Render');
} else {
console.log('Subsequent Render');
}
});
return isMount ? <p>First Render</p> : <p>Subsequent Render</p>;
};
如果你感兴趣,这里有一个测试:
import { renderHook } from '@testing-library/react-hooks';
import { useIsMount } from '../useIsMount';
describe('useIsMount', () => {
it('should be true on first render and false after', () => {
const { result, rerender } = renderHook(() => useIsMount());
expect(result.current).toEqual(true);
rerender();
expect(result.current).toEqual(false);
rerender();
expect(result.current).toEqual(false);
});
});
我们的用例是隐藏动画元素,如果初始道具表明它们应该被隐藏。在后来的渲染中,如果道具改变了,我们确实希望元素动画出来。
我找到了一个更简单的解决方案,不需要使用另一个钩子,但它有缺点。
useEffect(() => {
// skip initial render
return () => {
// do something with dependency
}
}, [dependency])
这只是一个例子,如果您的案例非常简单,那么还有其他方法可以做到这一点。
这样做的缺点是您不能有清理效果,并且只有在依赖数组第二次更改时才会执行。
这不建议使用,你应该使用其他答案所说的,但是我只是在这里添加了这个,这样人们就知道有不止一种方法可以做到这一点。
更清楚地说,你不应该使用这种方法来解决问题中的问题(跳过初始渲染),这只是为了教学目的,表明你可以用不同的方式做同样的事情。如果需要跳过初始渲染,请使用其他答案的方法。