Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React + Redux, How to render not after each dispatch, but after several?

I am trying to make multiple changes to the store, but not render till all changes are done. I wanted to do this with redux-thunk.

Here is my action creator:

function addProp(name, value) {
    return { type:'ADD_PROP', name, value }
}

function multiGeoChanges(...changes) {
    // my goal here is to make multiple changes to geo, and make sure that react doesnt update the render till the end
    return async function(dispatch, getState) {
        for (let change of changes) {
            dispatch(change);
            await promiseTimeout(2000);
        }
    }
}

I dispatch my async action creator like this:

store.dispatch(multiGeoChanges(addProp(1, "val1"), addProp(2, "val2"), addProp(3, "val3")));

However this is causing react to render after each dispatch. I am new to redux-thunk, I never used async middleware, but I thought it could help me here.

like image 950
Noitidart Avatar asked Jan 14 '17 02:01

Noitidart


People also ask

Can I dispatch multiple actions Redux?

Using an async middleware like Redux Thunk certainly enables scenarios such as dispatching multiple distinct but related actions in a row, dispatching actions to represent progression of an AJAX request, dispatching actions conditionally based on state, or even dispatching an action and checking the updated state ...

Which function is used to avoid multiple component updates due to multiple action dispatched to the store?

Redux notifies subscribers after each successfully dispatched action, and amongst those subscribers will be every connect ed component in the app. To optimise this, we can utilise redux-batched-subscribe , which is a store enhancer that lets you debounce subscriber calls for multiple dispatches.

Does Redux support multiple actions?

In Redux, actions are the JavaScript object which has information. Having multiple actions will need multiple action creators. These actions should be unique in redux. Especially, the type of action must be defined properly to identify that.

Can I dispatch more than one action?

The answer of course is, yes, just either call dispatch multiple times or iterate dispatch over an array. Usually, though, if you're dispatching multiple actions like that, it's a sign that you might want to look into creating yet another action to better encode the intent behind the cause of all those other actions.


2 Answers

@Kokovin Vladislav's answer is correct. To add some additional context:

Redux will notify all subscribers after every dispatch. To cut down on re-renders, either dispatch fewer times, or use one of several approaches for "batching" dispatches and notifications. For more info, see the Redux FAQ on update events: http://redux.js.org/docs/faq/Performance.html#performance-update-events .

I also recently wrote a couple of blog posts that relate to this topic. Idiomatic Redux: Thoughts on Thunks, Sagas, Abstraction, and Reusability discusses the pros and cons of using thunks, and summarizes several ways to handle batching of dispatches. Practical Redux Part 6: Connected Lists, Forms, and Performance describes several key aspects to be aware of regarding Redux performance.

Finally, there's several other libraries that can help with batching up store change notifications. See the Store#Store Change Subscriptions section of my Redux addons catalog for a list of relevant addons. In particular, you might be interested in https://github.com/manaflair/redux-batch , which will allow you to dispatch an array of actions with only a single notification event.

like image 68
markerikson Avatar answered Sep 19 '22 13:09

markerikson


There are ways to achieve the goal:

Classic way:

usually: Actions describe the fact that something happened, but don't specify how the application's state changes in response. This is the job of reducers. That also means that actions are not setters.

Thus, you could describe what has happened and accumulate changes, and dispatch one action something like:

const multipleAddProp = (changedProps) =>({
   type:'MULTIPLE_ADD_PROP', changedProps
});

And then react on action in reducer:

const geo=(state,action)=>{
   ...
   switch (action.type){
   case 'MULTIPLE_ADD_PROP':
     // apply new props
   ...
   }
}

Another way When rerendering is critical :

then you can consider to limit components, which could be rerendered on state change. For example you can use shouldComponentUpdate to check whether component should be rendered or not. Also you could use reselect, in order to not rerender connected components after calculating derived data...


Non standard way: redux-batched-action

It works something like transaction.

In this example, the subscribers would be notified once:

import { batchActions } from 'redux-batched-actions';

const multiGeoChanges=(...arrayOfActions)=> dispatch => {
    dispatch( batchActions(arrayOfActions) );
}
like image 24
Kokovin Vladislav Avatar answered Sep 21 '22 13:09

Kokovin Vladislav