State Normalization
Normalization means structuring nested/relational data as flat lookup tables, similar to a database.
The problem - nested state
ts
// nested - hard to update
const state = {
posts: [
{
id: '1',
title: 'Hello',
author: { id: 'u1', name: 'Alice', avatar: '...' },
comments: [
{ id: 'c1', text: 'Nice!', author: { id: 'u2', name: 'Bob' } },
]
}
]
};
// updating Alice's name requires finding her in every post and commentNormalized state - flat lookup tables
ts
const state = {
users: {
u1: { id: 'u1', name: 'Alice', avatar: '...' },
u2: { id: 'u2', name: 'Bob' },
},
posts: {
'1': { id: '1', title: 'Hello', authorId: 'u1', commentIds: ['c1'] },
},
comments: {
c1: { id: 'c1', text: 'Nice!', authorId: 'u2' },
},
};
// updating Alice's name - one place
state.users.u1.name = 'Alicia';Redux Toolkit - createEntityAdapter
ts
import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
const usersAdapter = createEntityAdapter<User>();
const usersSlice = createSlice({
name: 'users',
initialState: usersAdapter.getInitialState(),
reducers: {
addUser: usersAdapter.addOne,
updateUser: usersAdapter.updateOne,
removeUser: usersAdapter.removeOne,
setAllUsers: usersAdapter.setAll,
},
});
// selectors come for free
const { selectAll, selectById, selectIds } = usersAdapter.getSelectors(
(state: RootState) => state.users
);When to normalize
- The same entity appears in multiple places.
- You perform frequent updates to nested items.
- You render large lists that need fast lookups by ID.
- You're building a complex relational data model.
If your data comes from a REST API with nested relationships, normalization pays off quickly. For simple list display, it may be overkill.
updated
did you know it?