Single Source of Truth
Single Source of Truth
The “Single Source of Truth” (SSOT) is a fundamental software engineering principle that states that every piece of data should have exactly one place where it is stored and officially managed.
In React, violating this principle is the #1 cause of synchronization bugs (where one part of the UI shows outdated or conflicting information compared to another part).
The Anti-Pattern: Duplicating State
The most common way developers violate SSOT in React is by copying props into a component’s local state, or by creating “derived state.”
❌ Bad: Duplicating Truth
Imagine a UserDashboard component that fetches a user object and passes it to an EditProfileForm.
// ❌ Violates Single Source of Truth
function EditProfileForm({ user }) {
// The 'user' object is now stored in TWO places:
// 1. The Parent's state (the official truth)
// 2. This Component's local state (a copied truth)
const [localUser, setLocalUser] = useState(user);
return (
<input
value={localUser.name}
onChange={e => setLocalUser({ ...localUser, name: e.target.value })}
/>
);
}
Why this is dangerous:
If the Parent component fetches updated user data from the server (e.g., someone else changed the name in another browser tab), the user prop will update.
However, because useState(user) only runs on the initial render, localUser will not update. The EditProfileForm will now show stale, outdated data, completely ignoring the new props. The UI is out of sync because there are two competing versions of the truth.
The Solution: Calculate on the fly or Lift State Up
To maintain a Single Source of Truth, you should never duplicate data.
Solution 1: Calculate on the fly (for derived data)
If a piece of data can be calculated from existing props or state, don’t put it in state. Calculate it during the render cycle. (See Derived State for more details).
Solution 2: Lift State Up (for shared data)
If two components need to edit the same data, they shouldn’t maintain their own copies. The state should be moved up to their nearest common parent. The parent becomes the Single Source of Truth, and passes the value and a setter function down to the children. (See Lifting State Up).
Solution 3: Controlled Components (for forms)
In the EditProfileForm example, the correct approach is to make it a fully Controlled Component. It should have no local state. The Parent should hold the truth and pass an onChange handler down.
// ✅ Obeys Single Source of Truth
function EditProfileForm({ user, onNameChange }) {
// No local state! This component just displays the truth it is given.
return (
<input
value={user.name}
onChange={e => onNameChange(e.target.value)}
/>
);
}
By strictly adhering to the Single Source of Truth, you eliminate an entire class of synchronization bugs from your React applications.
Interview Questions
Q: Why is duplicating data across multiple state variables dangerous?
A: It creates multiple sources of truth. If you update the data in one state but forget to update it in the other, your UI falls out of sync and displays contradictory information. Always derive data from a single state variable on the fly during render.