我一直在尝试通过防止以下示例中的容器组件每次子组件更新时都重新呈现来优化应用程序。该应用示例仅包含一个通过密钥更新的计数器。尽管我在实际应用中使用了多个计数器,但我将示例简化为一个计数器。
它的工作原理是每秒调度一次增量操作,该操作会更新redux状态。容器通过状态保持不变的每个计数器(在本例中为一个)进行映射,并呈现一个仅显示计数的子组件。
我已经研究过使用PureComponent和shouldComponentUpdate,但是无法停止重新渲染,我也不确定后者是否是最好的方法。从类似的问题中,我搜集到的问题可能是容器和子组件都在状态中引用同一对象,因此都被更新了。此处的沙盒示例:https://codesandbox.io/s/nostalgic-rubin-k1gxy
容器
import os
import numpy as np
# fix incorrect order in foregroud objects
os.environ['ETS_TOOLKIT'] = 'qt4'
os.environ['QT_API'] = 'pyqt'
from mayavi import mlab
def plot_cell(cell, mlab):
for nr, i in enumerate(cell):
coord = np.zeros((4, 3), dtype=float)
coord[1] = i
for nr2, j in enumerate(cell):
if nr == nr2:
continue
coord[2] = i + j
for nr3, k in enumerate(cell):
if nr3 == nr or nr3 == nr2:
continue
coord[3] = i + j + k
mlab.plot3d(*coord.T, color=(0, 0, 0), line_width=0.01)
# generate data in non-cartesian coordinate system
scaled_coord = [np.linspace(0, 1, 20, endpoint=False) for i in range(3)]
XYZ = np.array(np.meshgrid(*scaled_coord, indexing="ij"))
data = np.sin(2*np.pi*XYZ[0])*np.sin(2*np.pi*XYZ[1])*np.sin(2*np.pi*XYZ[2])
plot_cell(np.eye(3), mlab)
mlab.contour3d(*XYZ, data)
mlab.savefig("old_coord.png")
mlab.close()
# transform to cartesian coordinates
cell = np.array(
[[ 1. , 0. , 0. ],
[-0.5 , 0.87, 0. ],
[ 0. , 0. , 3.07]])
transformation_matrix = cell.T
XYZ2 = np.einsum('ij,jabc->iabc', transformation_matrix, XYZ)
# plot transformed result
plot_cell(cell, mlab)
mlab.contour3d(*XYZ2, data)
mlab.savefig("new_coord.png")
mlab.close()
# plot points
plot_cell(cell, mlab)
mlab.points3d(*XYZ2, data)
mlab.savefig("new_coord_expected.png")
mlab.close()
孩子
class CounterContainer extends React.PureComponent {
renderWatches = () => {
//was some map logic here originally hence separate method
const { counters } = this.props;
const counterKeys = Object.keys(counters);
return counterKeys.map(key => {
return <SingleCounter key={key} mapKey={key} />;
});
};
render() {
console.log("CounterContainer rendered");
return <div>{this.renderWatches()}</div>;
}
}
const mapStateToProps = state => {
return {
counters: state.counters
};
};
export default connect(mapStateToProps)(CounterContainer);
看看控制台日志,理想情况下,我希望看到每次计数器增加时子组件都会重新渲染,但是容器应该只渲染一次(或在实际应用中,只要添加另一个计数器)>