Suggest an editImprove this articleRefine the answer for “What does "state normalization" do?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**State normalization** is a way to store data in state in a "flat", structured form, in order to avoid duplicating data, simplify updates, and reduce the number of re-renders. **Key point:** an object is stored in one place, and other entities reference it via an ID, so changing it doesn't require updating every copy.Shown above the full answer for quick recall.Answer (EN)Image## What state normalization is **State normalization** is a way to **store data in state in a "flat", structured form**, in order to: - **avoid duplicating** data, - **simplify updates**, - **reduce the number of re-renders**, - and make the data **predictable** and **easy to cache**. --- ### Example without normalization (bad) ```javascript const state = { posts: [ { id: 1, title: "React guide", author: { id: 10, name: "Tim" } }, { id: 2, title: "Redux patterns", author: { id: 10, name: "Tim" } // the author is duplicated } ] }; ``` Here, the author object is duplicated in every post. If the author changes their name, you have to go through all the posts and update the copy. Also, every change to posts triggers mass re-renders. --- ### Example with normalization ```javascript const state = { posts: [1, 2], // just IDs users: { // dictionary of entities by ID 10: { id: 10, name: "Tim" } }, entities: { posts: { 1: { id: 1, title: "React guide", authorId: 10 }, 2: { id: 2, title: "Redux patterns", authorId: 10 } } } }; ``` Now: - The author is stored in one place (users[10]); - Posts reference the author via authorId; - When the author changes, you don't need to update all the posts. --- ## Why this matters for React performance 1. **Fewer re-renders** - When an entity is updated, React can re-render only the components that depend on that specific ID. - There's no "chain" reaction through nested objects. 2. **Data is easy to compare (shallow compare)** - Objects and arrays are less nested, so === and React.memo work more efficiently. 3. **Updates are simpler** - Changing a specific item is just an update to state.entities.posts[id]. - No need to iterate over the whole array. 4. **Cache and selectors are optimized** - Memoized selectors (for example, in Redux Toolkit with createSelector) work faster and more consistently. --- ## Analogy Imagine your state is a miniature database. Normalization turns it into tables with relationships (1:1, 1:n), instead of nested objects (like "JSON inside JSON"). --- ## This is especially useful in React / Redux In Redux Toolkit and RTK Query, this is the recommended practice. The official normalizr library even automates the transformation: ```javascript import { normalize, schema } from 'normalizr'; const user = new schema.Entity('users'); const post = new schema.Entity('posts', { author: user }); const normalizedData = normalize(originalData, [post]); ``` Result: ```javascript { entities: { users: { '10': { id: 10, name: 'Tim' } }, posts: { '1': { id: 1, title: 'React guide', author: 10 }, '2': { id: 2, title: 'Redux patterns', author: 10 } } }, result: ['1', '2'] } ``` --- ## Example in the context of React components ### Without normalization: ```javascript function Post({ post }) { return ( <div> <h2>{post.title}</h2> <p>{post.author.name}</p> </div> ); } ``` If the author's name updates, React will re-render all the posts, because post.author is a new object in each one. --- ### With normalization: ```javascript function Post({ postId }) { const post = useSelector(state => state.entities.posts[postId]); const author = useSelector(state => state.entities.users[post.authorId]); return ( <div> <h2>{post.title}</h2> <p>{author.name}</p> </div> ); } ``` Now updating author.name will only touch the components that depend on authorId, not the entire list of posts. --- ## Additional benefits of normalization | Benefit | Description | |---|---| | Simple structure | You always know where to look for data | | Easy to update and delete | You change by ID, without complex nesting | | Clear relationships between entities | "One-to-many", "many-to-many" | | Compatible with selectors | Works great with memoization (useMemo, reselect) | | Less JSON parsing and diffing | Shallow comparison is enough | --- ## When you shouldn't normalize Excessive normalization is harmful when: - There isn't much data (10-20 records, a simple form); - Updates are rare and don't touch subtrees; - The data structure is static (for example, a list of tabs or a simple menu). Normalization is needed where there is interrelated data and frequent updates. --- ## Summary | What it does | Why it's needed | |---|---| | Stores data "flat" (by ID) | Eliminates duplication | | Preserves relationships via ID | Lets you update only the entities that need it | | Reduces the number of re-renders | Improves performance | | Makes the logic simpler | Data becomes predictable | | Works like a mini database | Easy to update, search, and cache | --- State normalization = a database inside React state. > One source of truth for each entity: fewer re-renders, fewer bugs, higher performance.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.