【发布时间】:2020-04-25 17:51:48
【问题描述】:
我有一个渲染 PureComponents 网格的 React / Redux 应用程序。我希望组件仅在道具值更改时重新渲染,但实际上所有组件都会在任何要存储的更新时重新渲染。该问题似乎是由数组属性引起的。
我已在this sandbox 中重现了该问题。在这个最小示例中,渲染了 Cell 组件的两个实例。每个都显示一个单独记录在存储中的值,并且可以通过一个按钮单独增加或减少。
Cell.js
import React, { PureComponent } from "react";
import { connect } from "react-redux";
import { incrementAction, decreaseAction } from "./actions";
class Cell extends PureComponent {
render() {
const { index, value, incrementAction, decreaseAction } = this.props;
console.log("render cell with index", index);
return (
<div>
<h1>{value}</h1>
<button onClick={incrementAction}>increment</button>
<button onClick={decreaseAction}>decrease</button>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => ({
value: ownProps.index === 1 ? state.value1 : state.value2,
myArray: [0, 1, 2]
});
const mapDispatchToProps = (dispatch, ownProps) => ({
incrementAction: () => dispatch(incrementAction(ownProps.index)),
decreaseAction: () => dispatch(decreaseAction(ownProps.index))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(Cell);
如果您检查控制台,您应该会看到,当您单击一个按钮时,两个单元都会重新渲染。
如果您在 mapStateToProps 中注释掉 myArray 属性,则行为会发生变化,因此只有您单击的单元格会重新呈现。
因此,由于静态数组属性,PureComponent 似乎在对存储进行任何更改时重新渲染。
在我的真实应用中,数组也来自存储,如果数组值发生变化,Cell 应该重新渲染,但沙盒示例显示了静态数组属性如何触发重新渲染。
有什么方法可以为 PureComponent 提供一个数组 prop 并让它仅在 prop 更改时重新渲染?谢谢。
编辑:我 updated the sandbox 按照 Domino987 的建议将 myArray 移动到存储中,并添加一个函数来计算 Cell 组件所需的子数组 - 这是我真正的应用程序所做的。我已经添加了重新选择和重新选择的记忆,我已经把它变成了一个功能组件而不是 PureComponent。据我所知,这现在可以工作了——当你点击一个按钮时,只有一个 Cell 会重新渲染。耶!
在actions.js中:
import createCachedSelector from "re-reselect";
export function getMyArray(state, index) {
console.log("getMyArrayCached for index", index);
return state.myArray;
}
export function getIndex(state, index) {
return index;
}
export const getMyArrayCached = createCachedSelector(
getMyArray,
getIndex,
(myArray, index) =>
myArray.map(elm => {
return elm[index - 1];
})
)((_state_, index) => index);
在 reducer.js 中:
const initialState = {
value1: 0,
value2: 0,
myArray: [[1, 2], [1, 2], [1, 2]]
};
在 Cell.js 中:
const mapStateToProps = (state, ownProps) => {
const value = ownProps.index === 1 ? state.value1 : state.value2;
return {
value,
myArray: getMyArrayCached(state, ownProps.index)
}};
【问题讨论】:
标签: reactjs optimization redux