How to update redux state further down the tree

For a given reducer, my redux state tree usually looks something like this:

{ someField: 'some value', // ... more fields metadata: { pending: false, fetched: true, } } 

Usually, when I execute the async request, I run the SOME_ACTION_REQUEST action, which sets the metadata.pending property to true. It reset will again be false when a subsequent SOME_ACTION_RESPONSE or SOME_ACTION_ERROR event occurs later.

However, the state update method is somewhat detailed:

 case actions.SOME_ACTION_REQUEST: { return { ...state, metadata: { ...state.metadata, pending: true }, }; } 

Is there an easier way to do this?

Object.assign({}, state, { metadata: { pending: true } }) also not readable.

+5
source share
3 answers

You can use the nested gear structure.

where there is metadata for the function / reducer name, call this to change the fields.

Code example

 const metadata = (state = [], action = {}) => { switch (action.type) { case actions.SOME_ACTION_REQUEST:: return {...state, ...action.payload.metadata}; default: return state; } }; const someReducer = (state = initalState, action = {}) => { let metadata = {}; switch (action.type) { case actions.SOME_ACTION_REQUEST: { metadata = metadata(state.metadata, action) return { ...state, ...metadata }; } } }; 
+1
source

This is a fairly typical example of performing constant data updates. You can read the new section, β€œStructuring Gearboxes,” in Redux docs for more information, such as the Prerequisite Concepts and Fixed Pattern Pages .

+2
source

Yes, this is actually a Redux flaw, and not only that - if you use MobX, you will have the same problem. So, the answer is to generalize it somehow - write factory reducers that will take constants as arguments and combine them only once and reuse them for all asynchronous actions.

I created the library just for this problem, so feel free to look at it. Also, just keep in mind that raw Redux is pretty verbose anyway, and try to better understand your domain model. Your example would look like this:

 import { createTile } from 'redux-tiles'; const someTile = createTile({ type: ['some', 'example'], fn: ({ api, params }) => api.get('/some/request', params), }); dispatch(actions.some.example(params)); selectors.some.example(state)); // { isPending: true, error: null, data: null } 

The data of the last selector will be updated automatically after receiving a response - so you do not need to write such materials manually.

Another problem is nested updates, and you will have to do the same, but with a lot of verbosity that I have always tried to solve. But, of course, this is a fairly simple library that tries to cover simple use - for complex ones, I definitely recommend that you try something individual.

0
source

Source: https://habr.com/ru/post/1257526/


All Articles