React: useEffect vs useMemo vs useState



我试图在网上找到一个简洁的答案,但没有运气。

关于useEffectuseMemouseState之间的差异,以下是否正确?

  • useStateuseMemo都会记住跨渲染的值。区别在于:
    • useMemo不会导致重新渲染,而useState会导致重新渲染
    • useMemo仅在其依赖项(如果有)发生更改时运行,而setSomeState(useState返回的第二个数组项)没有这样的依赖项数组
  • useMemouseEffect仅在其依赖项更改(如果有)时运行。区别在于:
    • useEffect在渲染发生运行,而useMemo在渲染发生之前运行

我错过了任何其他关键差异吗?

你的观点基本上是正确的,一些小的澄清:

useState导致在调用 setState 方法(返回的数组中的第二个元素)时重新呈现。它没有任何依赖关系,如useMemo或useEffect。

useMemo仅在其依赖数组中的元素发生变化时才重新计算值(如果没有依赖关系 - 即数组为空,它只会重新计算一次)。如果省略数组,它将在每次渲染时重新计算。调用该函数不会导致重新呈现。此外,它在组件渲染期间而不是之前运行。

useEffect在每次渲染调用,如果其依赖数组中的元素已更改或数组被遗漏。如果阵列为空,则只会在初始装载时运行一次(如果返回清理函数,则卸载)。

您可以随时查看 Hooks API 参考,在我看来,这是一个非常可靠的文档

  • useEffect(callback, [dependency])的返回值是void并在render()之后执行。
  • useMemo(callback, [dependency])的返回值不是void而是记忆值,它在render()期间执行。

在以下情况下,useEffect()可以提供与useMemo()相同的优化:

  • 昂贵的计算中使用的状态变量(即 count1)是 useImpact 的唯一依赖项。
  • 当我们不介意将昂贵的计算值存储在状态变量中时。
const [count1, setCount1] = useState(0);
const [expensiveValue, setExpensiveValue] = useState(null);
useEffect(() => {
console.log("I am performing expensive computation");
setExpensiveValue(((count1 * 1000) % 12.4) * 51000 - 4000);
}, [count1]);   
  • 唯一的区别是,useEffect()使昂贵的计算值在render()后可用,而useMemo()使值在render()期间可用。
  • 大多数情况下,这并不重要,因为如果该值已计算用于在UI中呈现,则useEffect()useMemo()都将在浏览器完成绘制之前使该值可用。

useMemo用于记忆属于组件但不一定属于组件状态的计算/值,例如验证、依赖组件且必须返回值的方法;

const validEmail = React.useMemo(() => validateEmail(email), [email])
/* Now use 'validEmail' variable across the component, 
whereas 'useEffect' return value is void and only used for unmounting duties, 
like unsubscribing from subscription e.g. removeInterval*/

从文档:

请记住,传递给 useMemo 的函数在渲染期间运行。不要在那里做任何渲染时通常不会做的事情。例如,副作用属于useEffect,而不是useMemo。

<小时 />

useEffect副作用:

突变、订阅、计时器、日志记录和 其他副作用

setStatesetTimeoutsetIntervalref分配、API 调用或任何不执行繁重计算的东西都属于这里。

还要记住,优化是有代价的,因此 React 建议仅在需要记忆/优化时才使用useMemo,在其他情况下,在必要时依赖useEffect

您可以依赖 useMemo 作为性能优化,而不是语义保证。

将来,React 可能会选择"忘记"一些以前记住的 值并在下次渲染时重新计算它们,例如释放内存 屏幕外组件。编写代码,使其在没有的情况下仍然可以工作 useMemo — 然后添加它以优化性能。


[state, setState] = useState()更新给定的状态变量,该变量在重新渲染期间保持稳定,并调用附加到它setState触发重新渲染。这个钩子的目的与上述两个钩子没有太大关系。

最新更新