Don't use useEffect to sync state that can be computed from existing state or props. Derived values should be calculated during render, not in effects. Effects for derived state cause extra renders, race conditions, and stale UI that flash incorrect data before correcting.
Why This Matters
useEffect for derived state causes a double-render on every change: first the component renders with stale derived state, then the effect fires and triggers a second render with the correct value. Users see a flash of wrong data, and in concurrent mode the stale render can interleave with other updates, producing race conditions that are nearly impossible to reproduce.
When you store a value in state that could be computed from other state or props, and then use useEffect to keep it "in sync," you introduce a subtle but damaging pattern. The component renders once with the stale derived value, then the effect fires and sets state again, causing a second render.
This double-render is not just a performance issue. During the first render, your UI shows incorrect data. In React 18's concurrent mode, these stale intermediate renders can interleave with other updates, producing race conditions that are extremely difficult to debug.
The fix is simple: compute derived values directly during render. React is designed for this — it's just a function call.
The rule
If a value can be computed from existing state or props, calculate it during render instead of storing it in state and syncing with useEffect. Use useMemo only when the computation is genuinely expensive (measurable with profiling).