React 组件和 Hook 必须是幂等的
React 中的一个核心概念是保持纯粹。一个纯组件或 Hook 应该是幂等的 ——每次使用相同的输入组件输入的 props、state、context 以及 Hook 输入的参数运行它你总是得到相同的结果。组件必须始终根据其输入props、state、和 context返回相同的输出。这被称为“幂等性”。幂等性是函数式编程中经常使用的一个术语它指的是只要你使用相同的输入运行代码 得到的结果总是一样的。这意味着为了遵循这一规则所有 在渲染期间 执行的代码也必须是幂等的。例如以下这行代码就不是幂等的因此包含这行代码的组件也不是幂等的function Clock() { const time new Date(); // 错误的总是返回不同的结果 return span{time.toLocaleString()}/span}new Date() 函数不是幂等的因为每次调用时返回的结果都不同它总是返回调用时刻的日期和时间。当你渲染上面的组件时屏幕上显示的时间将会停留在组件被渲染的那一刻的时间。类似地像 Math.random() 这样的函数也不是幂等的因为即使输入相同它们每次调用也都会返回不同的结果。这并不意味着你完全不能使用像 new Date() 这样非幂等的函数你只需要避免 在渲染过程 中使用它们即可。在这种情况下我们可以使用一个 Effect 来将最新的日期与这个组件进行“同步”import { useState, useEffect } from react; function useTime() { // 1. 跟踪当前日期的状态。useState 接受一个初始化函数作为其 // 初始状态。它只在调用 Hook 时运行一次因此只有调用 Hook 时的 // 当前日期才被首先设置。 const [time, setTime] useState(() new Date()); useEffect(() { // 2. 使用 setInterval 每秒更新当前日期。 const id setInterval(() { setTime(new Date()); // ✅ 正确的非幂等代码不再在渲染中运行。 }, 1000); // 3. 返回一个清理函数这样我们就不会忘记清理 setInterval 定时器导致内存泄漏。 return () clearInterval(id); }, []); return time;} export default function Clock() { const time useTime(); return span{time.toLocaleString()}/span;}通过将非幂等的 new Date() 调用包装在一个 Effect 中就可以将这个计算移动到 渲染之外。如果你不需要将某些外部状态与 React 同步只需要在响应用户交互时更新你可以考虑使用一个 事件处理函数。