Managing filtered lists in state often leads to bugs and extra renders. Learn why calculating values on the fly keeps your UI in sync and your code clean.

The golden rule is simple: if you can calculate it from existing state, don’t store it. When you store derived data in state, you are essentially adding a middleman that creates synchronization drift.
Synchronization drift occurs when a developer stores derived data in a separate state variable, such as keeping a filteredList state alongside a rawData state. This creates a situation where two "clocks" must be manually kept in sync. If a developer forgets to update the second state when the first one changes—like when new data arrives from a server—the UI will display stale or incorrect information. This approach also often leads to "double renders" because React must first render the change to the source state and then trigger a second render once a useEffect updates the derived state.
The golden rule is that if a value can be calculated from existing props or state, it should not be stored in its own state. You should treat your component as a pure function where props and raw data are the "sources of truth" and everything else is a "transformation." For example, instead of using useState for a boolean like isEmpty, you should simply calculate const isEmpty = data.length === 0 directly in the component body. This ensures the UI is always a direct, accurate reflection of the underlying data.
While most JavaScript array operations like filtering or sorting are fast enough to run on every render, useMemo should be used in two specific scenarios. First, it acts as a "sticky note" for expensive calculations that take longer than one millisecond, preventing them from re-running unless their specific dependencies change. Second, it is used to maintain "referential equality." Since React compares objects and arrays by reference, useMemo ensures that a derived array maintains the same identity across renders, preventing unnecessary re-render waterfalls in child components wrapped in React.memo.
The "State + Effect" combo—where a useState hook is immediately followed by a useEffect that updates a different state—is a primary indicator of duplicated state. This pattern adds unnecessary cognitive load to the code and makes it harder to test because the logic is trapped inside lifecycle hooks. By refactoring this into a simple variable or a derived calculation, you remove the "middleman," reduce the lines of code, and eliminate the possibility of "impossible states" where different parts of the UI disagree with each other.
From Columbia University alumni built in San Francisco
"Instead of endless scrolling, I just hit play on BeFreed. It saves me so much time."
"I never knew where to start with nonfiction—BeFreed’s book lists turned into podcasts gave me a clear path."
"Perfect balance between learning and entertainment. Finished ‘Thinking, Fast and Slow’ on my commute this week."
"Crazy how much I learned while walking the dog. BeFreed = small habits → big gains."
"Reading used to feel like a chore. Now it’s just part of my lifestyle."
"Feels effortless compared to reading. I’ve finished 6 books this month already."
"BeFreed turned my guilty doomscrolling into something that feels productive and inspiring."
"BeFreed turned my commute into learning time. 20-min podcasts are perfect for finishing books I never had time for."
"BeFreed replaced my podcast queue. Imagine Spotify for books — that’s it. 🙌"
"It is great for me to learn something from the book without reading it."
"The themed book list podcasts help me connect ideas across authors—like a guided audio journey."
"Makes me feel smarter every time before going to work"
From Columbia University alumni built in San Francisco
