Better Redux Store Structure

Mitsuhide Ohi
3 min readFeb 19, 2018

--

Redux store structure without consideration makes it difficult to write efficient or readable code.
Sometimes you might need huge refactoring if these flaws come to the light in the middle of the development.
Trust me. I’ve been through this.
I’m going to share some tips in the determination of Redux Store structure.

Use Model Class for the initialState

Instead of declaring initial state as an object in the reducer, should declare the model class and use the instance for initial state.
This brings clarity to the structure of the store from anywhere in your project so that you or your colleges won’t get confused what property can be set or retrieved.
Also, you can move updating logic from reducer to the model and write some test for it.

For the case like below.

const initialState = {
title: null,
author: null
}
function book (state = initialState, action) {
switch (action.type) {
case 'SET_TITLE':
return {...state, title: action.title}
case 'SET_AUTHOR':
return {...state, author: action.author}
default:
return state
}
}

Better to have class like this.

class Book {
constructor (title, author) {
this.setTitle(title || null)
this.setAuthor(author || null)
}
setTitle (title) {
this.title = title
return this
}
setAuthor (author) {
this.author = author
return this
}
}

Use it for instantiating the initial state of the reducer. For updating values, create new object through method in model.

function book (state = new Book(), action) {
switch (action.type) {
case 'SET_TITLE':
return state.setTitle(action.title)
case 'SET_AUTHOR':
return state.setAction(action.author)
default:
return state
}
}

However, this has more room for improvement. It can be more easy to maintain model class by extending Record class of Immutable.js so that you can use predefined handy methods and keep the immutability.

Use The Key-value Object to store iterative elements

Instead of using an array to store iterative elements, use the key-value object to store them so that you can reduce computational cost when you take out specified element in series.

In case you intend to have an array like below.

{
books: [
{
id: 'b1',
name: 'Lean React',
author: 'Don Juan'
},
{
id: 'b2',
name: 'React Thinking',
author: 'William Shakespeare'
},
{
id: 'b3',
name: '3 minutes React',
author: 'Nicolaus Copernicus'
}
]
}

You better to use Object instead.

{
books: {
b1: {
name: 'Lean React',
author: 'Don Juan'
},
b2: {
name: 'React Thinking',
author: 'William Shakespeare'
},
b3: {
name: '3 minutes React',
author: 'Nicolaus Copernicus'
}
}
}

You might gonna see the benefit of doing this when you have a huge set of data in it.
Just like the array, even you still can traverse all the elements with usingObject.keys.

Object.keys(books).forEach(key => {
const book = books[key]
console.log('name', book.name)
console.log('author', book.author)
})

Make it flat as possible

If you have deep nest in the structure, it would become hard to do anything like retrieve, update or delete. And what is worse, sometimes it makes data duplicates.

For the case like below.

{
owners: {
o1: {
name: 'Jhon',
books: {
b1: {
name: 'Lean React',
author: 'Don Juan'
},
b2: {
name: 'React Thinking',
author: 'William Shakespeare'
}
}
},
o2: {
name: 'Sam',
books: {
b2: {
name: 'React Thinking',
author: 'William Shakespeare'
},
b3: {
name: '3 minutes React',
author: 'Nicolaus Copernicus'
}
}
}
}
}

This can be normalize like this.

{
owners: {
o1: {
name: 'Jhon',
bookIds: [
'b1',
'b2'
]
},
o2: {
name: 'Sam',
bookIds: [
'b2',
'b3'
]
}
},
books: {
b1: {
name: 'Lean React',
author: 'Don Juan'
},
b2: {
name: 'React Thinking',
author: 'William Shakespeare'
},
b3: {
name: '3 minutes React',
author: 'Nicolaus Copernicus'
}
}
}

In this way, you can make it flat for sake of maintainability of the redux store data.

--

--

Responses (4)