问题描述
我有一个功能组件,该组件传递了有关从redux存储中提取内容的指令。
使用mapStatetoProps=(state,ownProps)
,我可以很高兴地从状态(存储)中拉出所需的项目-但是,以牺牲整个状态树中的任何更改为代价,这会触发重新运行mapStatetoProps和大量的重新渲染。
让我打开包装。
这是商店一部分的快照:
{
settings: {...stuff...},projects: [...stuff...],deFinitions: [...stuff...],themes: [...stuff...],surfaces: {
'6': { <--- VARIABLE PASSED TO COMPONENT
surface: {
STRIP: [..stuff..],GLOBAL: { <--- CATEGORY PASSED TO COMPONENT
disPLAY: {...stuff...},ASSIGNMENT: { <--- LIST OF required OBJECTS HAS
A_TRACK: { SUBCATEGORY AND TARGET (A_TRACK etc...)
value: 0,type: 'switch',label: 'TRACK'
},A_SEND: { <--- ANOTHER OBJECT I NEED TO GET
value: 0,label: 'SEND'
},A_PAN: {
value: 0,label: 'PAN'
},},FADER_BANKS: {...stuff...},STATUS: {...stuff...},LOTS_MORE_STUFF
我的父组件将必需的指令传递给孩子。
<RefmixerGroup
portId = {this.props.portId}
items={[
{parent: 'GLOBAL',group: "ASSIGNMENT",target: "A_TRACK"},{parent: 'GLOBAL',target: "A_SEND"},]
}
/>
mapStatetoProps非常简单:
const mapStatetoPropy = (state,ownProps) => {
return {
groupItems: getItemsFromState(state.surfaces[ownProps.portId].surface,ownProps.items)
}
}
const getItemsFromState = (subState,items)=>{
let groupItems=[]
for (let i = 0; i < items.length; i++) {
const item = items[i];
const base = subState[item.parent];
let groupItem = base[item.group][item.target]
groupItems.push({...groupItem,target: item.target})
}
return groupItems
}
但是因为我正在创建匹配项数组,所以我认为redux认为我应该订阅树中的每个项目……在这种情况下,当我只希望对找到的元素进行更改时,
surfaces[6].surface[GLOBAL][ASSIGNMENT][A_TRACK]
surfaces[6].surface[GLOBAL][ASSIGNMENT][A_SEND]
我尝试使用重新选择和重新选择而不是上面的getItemsFromState函数, 但所有结果相同。从表面[6]开始,该树中的任何更改都会触发mapsstatetoProps并重新渲染。
必须有解决办法,但我无法弄清楚。我尝试使用areStatesEqual
,但它仅提供nextState
和prevstate
,并且我需要ownProps
来计算相等性。我可能可以使用areStatePropsEqual
,但这仅在不必要地重新计算mapStatetoProps
之后起作用。
一定有办法!
解决方法
getItemsFromState
每次运行时都会创建一个新的groupItems
数组引用。每次 分派动作后都会调用它。从connect
re-renders any time any of the fields returned by mapState
have changed to a new reference开始,您的代码将迫使React-Redux每次都重新渲染。
这就是为什么you should use memoized selectors to only return new derived data references if the input references have changed(通常使用Reselect的createSelector
)的原因。如果您对Reselect的使用在这里没有帮助,则可能是您的选择器设置不正确,但是我需要查看具体示例以在此处提供建议。
这也是components should subscribe to the smallest amount of data that they actually need的原因。
如果您使用的是功能组件,建议您也使用useSelector
而不是connect
。