React + Redux,如何不是在每次调度之后而是在几次之后渲染?

IT技术 javascript reactjs redux react-redux redux-thunk
2021-05-10 07:09:21

我正在尝试对商店进行多项更改,但在完成所有更改之前不会渲染。我想用 redux-thunk 来做到这一点。

这是我的动作创建者:

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);
        }
    }
}

我像这样派遣我的异步动作创建者:

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

然而,这会导致在每个dispatch. 我是 redux-thunk 的新手,我从未使用过异步中间件,但我认为它可以帮助我。

4个回答

@Kokovin Vladislav 的回答是正确的。添加一些额外的上下文:

Redux 会在每次调度后通知所有订阅者为了减少重新渲染,要么减少分派次数,要么使用多种方法之一进行“批处理”分派和通知。有关更多信息,请参阅有关更新事件的 Redux 常见问题解答:http : //redux.js.org/docs/faq/Performance.html#performance-update-events

我最近还写了几篇与此主题相关的博客文章。 Idiomatic Redux: Thoughts on Thunks, Sagas, Abstraction, and Reusability讨论了使用 thunk 的利弊,并总结了几种处理分派批处理的方法。 Practical Redux Part 6: Connected Lists, Forms, and Performance描述了关于 Redux 性能需要注意的几个关键方面。

最后,还有其他几个库可以帮助批量处理商店更改通知。有关相关插件的列表,请参阅我的Redux 插件目录Store#Store Change Subscriptions部分特别是,您可能对https://github.com/manaflair/redux-batch感兴趣,它允许您仅使用单个通知事件调度一系列操作。

有几种方法可以实现目标:

经典方式:

通常:动作描述了某事发生事实,但不指定应用程序的状态如何响应变化。这是减速机的工作。这也意味着动作不是 setter

因此,你能描述发生了什么和积累的变化,并派遣一个 动作 是这样的:

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

然后对减速器中的动作做出react:

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

另一种方式当重新渲染很重要时:

那么您可以考虑限制可以在状态更改时重新呈现的组件。例如你可以shouldComponentUpdate用来检查组件是否应该被渲染。您也可以使用reselect,以便在计算派生数据后不重新渲染连接的组件...


非标准方式: redux-batched-action

它的工作原理类似于事务。

在此示例中,订阅者将收到一次通知:

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

const multiGeoChanges=(...arrayOfActions)=> dispatch => {
    dispatch( batchActions(arrayOfActions) );
}

在 react-redux 7.0.1+ 中,批处理现在是内置的。7.0.1 的发行说明:

https://github.com/reduxjs/react-redux/releases/tag/v7.0.1

批量更新

React 有一个 stable_batchedUpdates API,它用于将来自同一事件循环滴答的多个更新组合在一起。React 团队鼓励我们使用它,我们已经更新了我们的内部 Redux 订阅处理以利用这个 API。通过减少由 Redux 存储更新引起的不同渲染的数量,这也应该有助于提高性能。

function myThunk() {

   return (dispatch, getState) => {

       // should only result in one combined re-render, not two

       batch(() => {

           dispatch(increment());

           dispatch(increment());

       })

   }

}

根据设计,当由 store 持有的状态更改视图应呈现时。

您可以通过更新一次状态来避免这种情况。

如果您正在使用Promise,您可以使用Promise.all等待所有Promise解决,然后将计算结果发送到商店的新操作。https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

像这样的东西:

Promise.all([p1, p2, p3, p4, p5]).then(changes => { 
  dispatch(changes)
}, err => {
  // deal with error
});

当然,你需要一个处理许多props的动作,像addManyProps这样的东西应该更新一次状态,从而产生一个渲染。