我正在尝试对商店进行多项更改,但在完成所有更改之前不会进行渲染。我想用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的新手,我从未使用异步中间件,但我认为它可以帮助我。
答案 0 :(得分:8)
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性能的几个关键方面。
最后,还有其他几个库可以帮助批量存储更改通知。有关相关插件的列表,请参阅Store#Store Change Subscriptions的Redux addons catalog部分。特别是,您可能对https://github.com/manaflair/redux-batch感兴趣,这将允许您仅使用一个通知事件来分派一系列操作。
答案 1 :(得分:6)
有很多方法可以实现这个目标:
经典方式:
通常: 操作描述 事实发生了什么 ,但没有指定应用程序的状态如何响应变化。这是减速机的工作。 这也意味着操作不是设置者。
因此,您可以描述已发生的事情并积累更改,并发送一个 操作 类似的东西:
const multipleAddProp = (changedProps) =>({
type:'MULTIPLE_ADD_PROP', changedProps
});
然后对reducer中的动作做出反应:
const geo=(state,action)=>{
...
switch (action.type){
case 'MULTIPLE_ADD_PROP':
// apply new props
...
}
}
另一种方式重新渲染至关重要时:
然后你可以考虑限制组件,这些组件可以在状态变化时重新渲染。
例如,您可以使用shouldComponentUpdate
来检查组件是否正常
应该是否呈现。
您也可以使用重新选择,以便不重新渲染连接的组件
计算派生数据后......
非标准方式: redux-batched-action
它类似于交易。
在此示例中,订阅者将收到一次通知:
import { batchActions } from 'redux-batched-actions';
const multiGeoChanges=(...arrayOfActions)=> dispatch => {
dispatch( batchActions(arrayOfActions) );
}
答案 2 :(得分:3)
按照设计,当商店持有的状态改变视图时应该呈现。
您可以通过更新状态一次来避免这种情况。
如果您使用的是promises,则可以使用Promise.all
等待所有承诺解析,然后使用计算结果将新操作发送到商店。 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
});
当然,您需要一个可以处理许多道具的动作,例如addManyProps
,这应该更新状态一次,从而产生一个渲染。
答案 3 :(得分:0)
redux-batched-actions &#xA ;为redux批处理动作创建者和关联的高阶减少器,它允许为一系列动作批处理订阅者通知。

答案 4 :(得分:0)
稍晚一点,但是我认为这是一个更好的解决方案,它使您可以将meta.batch
添加到要批量合并为单个react
更新的操作中。另外,这种方法适用于异步操作。
import raf from 'raf'
import { batchedSubscribe } from 'redux-batched-subscribe'
let notify = null
let rafId = null
const shouldBatch = action => action?.meta?.batch
export const batchedSubscribeEnhancer = batchedSubscribe(freshNotify => (notify = freshNotify))
export const batchedSubscribeMiddleware = () => next => action => {
const resolved = next(action)
if (notify && rafId === null && !shouldBatch(action)) {
notify()
} else if (!rafId) {
rafId = raf(() => {
rafId = null
notify()
})
}
return resolved
}
然后连接到您的商店
mport { applyMiddleware, compose, createStore } from 'redux'
import { batchedSubscribeMiddleware, batchedSubscribeEnhancer } from './batching'
const store = createStore(
reducer,
intialState,
compose(
batchedSubscribeEnhancer,
applyMiddleware(batchedSubscribeMiddleware)
)
)
答案 5 :(得分:0)
在react-redux 7.0.1+中,批处理现已内置。 7.0.1发行说明:
https://github.com/reduxjs/react-redux/releases/tag/v7.0.1
批量更新
React具有一个unstant_batchedUpdates API,用于对其进行分组 来自同一事件循环刻度的多个更新。反应 团队鼓励我们使用此功能,并且我们更新了内部Redux 订阅处理以利用此API。这也应该有所帮助 通过减少独立渲染的数量来提高性能 由Redux商店更新引起。
function myThunk() {
return (dispatch, getState) => {
// should only result in one combined re-render, not two
batch(() => {
dispatch(increment());
dispatch(increment());
})
}
}