Momen Zalabany
Momen Zalabany

Reputation: 9007

is it possible to have nested reducers in redux?

given an app with initialStore = { users :{} } where every user is stored inside users by its id as a key, if a component shows list of users, when updating a single user inside this object, the whole list is re-rendered which is expected since the reducer did return a new object as a state although all that the reducer actually needed was changing a single key.

Example code

ducks/users.js
const LoadAllAction = ()=>({ type:'USERS/LOAD',users:{1:{id:1,if:0},2:{id:2,if:0}} });
const LoadSingleAction = ()=>({ type:'USERS/SINGLE',user:{id:2,if:1} });

//THIS REDUCER HANDLE THE USERS SLICE OF STORE
const reducer = (state={},action)=>{

if(action.type === 'USERS/LOAD')return action.users;

if(action.type === 'USERS/SINGLE')return Object.assign({},state,{[action.user.id]:action.user});

return state;
}

const rootReducer = combineReducers({users:reducer});
const store = createStore(rootReducer, {users:{}});

above is a setup of the problem i'm investigating.. now given a simple React component that use connect to subscribe to store

const UsersPage = props=>(
    <ul> 
         {Object.keys(props.users).map((u)=>(
           <li key={u.id}>ID :: {u.id}</li>
         ))}
    </ul>
  );

const mapStateToProps(state)=>({users:state.users});

const component = connect(mapStateToProps)(UsersPage);

now in component above, if a single user is changed the users store, the whole usersPage component will re-render.

given that users store can hold above 10,000 user. how can i upgrade my reducers/redux structure so that when a single user inside the users store is updated.. only components that listen to this single user re-render ?

i tried to split the above ul into two components puting li into separate component and connecting it to redux view connect passing the

///LiComponent connect function example
const mapStateToProps(state,ownProps)=>({users:state.users[ownProps.key]});

yet it now both ul, and li re-renders. so it occured to me that the problem is that my reducer return a new users store every time it needs to update a single user, so i need to have a sub reducer for every user if i want to prevent this from happening.

but from what i understand redux store need to be flat and reducers only slice by keys, not by sub keys.

-is it possible/ AND NORMAL/ that you nest reducers in redux ?

by normal i mean i saw tons of simple todos apps around that never saw a real world large scale app structure out there that can guide us out of this, so how does redux gurus does this while planing there apps ?

Upvotes: 4

Views: 2896

Answers (1)

markerikson
markerikson

Reputation: 67459

First: yes, it is absolutely possible to nest reducer functions in various way. They are, after all, just functions, and it's entirely up to you how you want to build up that logic.

The standard approach for the issue you're describing is to normalize your state, so that you have "lookup tables" where each item can be looked up by its ID, and arrays of IDs to represent all the items. The parent list would then be connected, retrieve an array of IDs, and pass one ID to each child list item. Each list item component would be connected, receive its item ID as a prop, and use that to look up its own item in mapState.

I've got a number of links that describe these types of approaches:

Upvotes: 3

Related Questions