Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to separate UI and application state in Redux

Tags:

reactjs

redux

When writing a react-redux application, I need to keep both application and UI state in the global state tree. What is the best approach to design it's shape?

Lets say I have a list of todo items:

{   items: [     { id: 1, text: 'Chew bubblegum' },     { id: 2, text: 'Kick ass' }   ] } 

Now I want to let the users select and expand the items. There are (at least) two options how to model the state shape:

{   items: [     { id: 1, text: 'Chew bubblegum', selected: true, expanded: false },     { id: 2, text: 'Kick ass', selected: false, expanded: false }   ] } 

But this is mixing the UI state (selected and expanded) with the application state. When I save the todo list to the server, I want to save just the application state, not the UI state (in real-world app, UI state can contain state of modal dialogs, error messages, validation status etc).

Another approach is to keep another array for the UI state of the items:

{   items: [     { id: 1, text: 'Chew bubblegum' },     { id: 2, text: 'Kick ass' }   ],   itemsState: [     { selected: true, expanded: false },     { selected: false, expanded: false }   ] } 

Then you have to combine those two states when rendering an item. I can imagine that you can zip those two arrays in the connect function to make rendering easy:

const TodoItem = ([item, itemState]) => ...; const TodoList = items => items.map(item => (<TodoItem item={item} />));  export default connect(state => _.zip(state.items, state.itemsState))(TodoList); 

But updates to state can be painful, because items and itemsState must be kept in sync:

  1. When removing an item, corresponding itemState must be removed.
  2. When reordering items, itemsState must be reordered too.
  3. When the list of todo items is updated from the server, it is necessary to keep ids in the UI state and do some reconciliation.

Is there any other option? Or is there any library that helps keeping the app state and UI state in sync?

like image 911
dkl Avatar asked Nov 05 '15 22:11

dkl


People also ask

Can Redux have multiple states?

Collection / Item Reducer Pattern​This pattern allows you to have multiple states and use a common reducer to update each state based on an additional parameter inside the action object.

Should I keep all component's state in Redux store?

Some users prefer to keep every single piece of data in Redux, to maintain a fully serializable and controlled version of their application at all times. Others prefer to keep non-critical or UI state, such as “is this dropdown currently open”, inside a component's internal state. Using local component state is fine.

Can we change Redux state directly?

Redux restricts updating the state to this method only. This strict way of updating the state ensures that the state can not be changed directly either by view or any network callback. The only way to update a state is by defining the action and then dispatching it. Remember that actions are plain JavaScript objects.


1 Answers

Another approach inspired by normalizr:

{     ids: [12,11], // registry and ordering     data: {         11: {text: 'Chew bubblegum'},         12: {text: 'Kick ass'}     },     ui: {         11: { selected: true, expanded: false },         12: { selected: false, expanded: false }     } } 
like image 102
Rick Jolly Avatar answered Sep 17 '22 14:09

Rick Jolly