何时使用函数式更新?A simple rule of thumb: when your new state depends on previous state.
You can’t rely on closure values because y capture a snapshot at render time;function updates always read from React’s internal latest value.
This pattern guarantees correctness even when multiple updates are queued.
从使用者痛点来看,闭包陷阱 & 更新顺序混乱怎么办?
If you see “ counter doesn’t increment” after several rapid clicks,it’s likely because you’re using stale closures.
A quick fix is to switch to function form or use refs to hold mutable values that survive across renders.
Avoid “magic numbers” in your logic;always calculate based on previous state rar than assuming a particular snapshot.
If you’re debugging async flows,remember that state updates are still batched and may occur after or synchronous code has run.
Certain edge cases can cause unexpected re-renders if you don’t account for event propagation and default behavior properly.
四、初始值很“贵”时怎么办?惰性初始化
The App.jsx file includes an expensive simulation function:
If your initial state requires such heavy computation—for example generating thousands of user objects—re are two typical ways:
jsx
// 写法 A – 不推荐
const = useState);
// 写法 B – 推荐
const = useState => heavyComputation);
写法 A:Synchronous call every render! Even though React ignores subsequent values after first mount,expensive function still runs on every render—wasting CPU time and memory allocation.
写法 B:Painless lazy initialization!
You pass a function reference that React only executes once during initial mount. Subsequent renders skip this call entirely because React sees that it was already initialized.
从使用者痛点来看,昂贵计算导致 UI 卡顿怎么办?
If you notice lagging during component mounting,check wher you inadvertently performed heavy work directly inside { }.
Lazily initialize only when needed .
Create separate worker threads via Web Workers for truly large computations if y block UI thread.
• Use profiling tools to confirm wher heavy functions run repeatedly.
• If possible。fetch data asynchronously instead of precomputing locally—fetch from API instead of generating dummy data on client side.
• When migrating legacy code where initial state is computed inline,refactor it into a separate hook or effect that runs only once => { /* compute */ },)`).
• Remember that memoization can also help avoid recomputing derived results unnecessarily but does not replace lazy init for *initial* values.
• In tests or SSR environments where hydration matters,consider using `process.env.NODE_ENV!== 'production'` guard around heavy logic.
These strategies help prevent UI freezes and reduce unnecessary CPU cycles.
五、不是所有的数据都需要变成 State
In App.jsx we have:
jsx
const = useState => heavyComputation);其实,const = useState;// 注意:filteredUsers 并不是 State,仅仅是计算得到的数据:
const filteredUsers = users.filter);
You typically only store “source-of-truth” pieces in State—those values that actually change over time due to user interaction or external events.
The variable "filteredUsers",however。is derived from both "users",which never changes after initialization in this example,and filter text input . Re‑computing it on every render keeps it up‑to‑date without extra maintenance cost.
If you store it as separate state:
jsx
const =useState;// you'd have to sync it whenever users or filterText changes。you introduce unnecessary complexity—and bugs if you forget sync logic.
This idea is known as **derived/derived-from-state** pattern:
Your component's rendering logic should stay pure—a composition of current props & state—and any derived calculations should be done inline or memoized with `useMemo` if y are expensive.
从使用者痛点来看,冗余状态导致内存泄漏 & 性能下降?
If you accidentally put computed lists into State and n trigger frequent re-renders without proper memoization,.filter)。you'll end up with O complexity per render cycle. This leads to jank especially on mobile devices.
Remember that deriving from props/state keeps components easier to reason about—you never have two sources describing same thing.