Blog #26: Don't let 'Single Source of Truth' become blind dogma
I used to believe every variable in an application must reside in a single Store. That was a costly mistake of thousands of lines of redundant code.
I used to be a fanatical follower of the slogan: "Single Source of Truth." In the early days of getting familiar with Redux, I believed that for an application to be predictable, every state—from User info to whether a dropdown is open or closed—must be centrally managed in the Global Store.
I believed it because it sounded like very "standard architecture." "If everything is in one place, I can easily debug with Redux DevTools, can Time Travel, and never fear data being out of sync." That was theory. But reality gave me a cold shower in a complex financial management Dashboard project.
1. Context: When the Store becomes a "trash heap"
The system at the time had dozens of charts and data tables. Because I believed in a Single Source of Truth, I pushed isSidebarOpen, isModalLoading, and even the inputValue of each search box into Redux.
The result? Every time a user typed a character, the entire massive Store updated, leading to 70% of unrelated components on the screen having to re-render because they were "listening" to some part of the Store. The project was so laggy that typing wasn't even smooth.
2. Concept: State Locality
The problem was that I had confused Global Truth (Data that truly needs sharing) and Ephemeral State (Temporary state that disappears when the component unmounts).
// How I used to do it (Sounds "correct" but is wrong)
const SearchComponent = () => {
const value = useSelector(state => state.search.tempValue);
const dispatch = useDispatch();
return <input value={value} onChange={(e) => dispatch(updateSearch(e.target.value))} />;
};
Why did this sound right? Because it followed the "One-way data flow" rule perfectly. But in reality, forcing an input to go all the way to the Global Store before returning to display itself is a massive waste of resources.
3. Common Mistake and Balance
A Junior will also often do what I did: fearing that state will be "scattered," so they push everything to Context or Store. They consider useState something "amateur" compared to Redux.
Comparison between two ways:
- Doing it "by the book" (dogmatically): Everything in the Store -> Easy to debug with tools but slow app, long code because of having to write Action/Reducer for even small things.
- Doing it practically (Balanced): State sits at the closest place where it's used.
- Dropdown open?
useStateat that component. - Product filtering data? Local state of that page.
- Login info? Global Store.
- Dropdown open?
Lesson Learned
I realized that "Single Source of Truth" does not mean "Single Object of Everything."
- When the old way is still correct: In very small apps, or data that truly needs to be synchronized across 3-4 different screens.
- When to avoid: Avoid pushing pure UI states (open/close, hover, input text) into the Global Store. It only makes your system heavier and harder to reuse components.
The truth doesn't lie in a single place; it sits at the most appropriate place for each component.
Notes on the day I learned to place values correctly.
Series • Part 26 of 50