在我的公司,我们正在将 Web 应用程序的前端迁移到 ReactJS。我们正在使用 create-react-app(更新到 v16),没有 Redux。现在我被困在一个可以通过下图简化结构的页面上:
三个组件(SearchableList、SelectableList 和 Map)显示的数据在componentDidMount()
MainContainer的方法中使用相同的后端请求进行检索。此请求的结果然后存储在 MainContainer 的状态中,并具有或多或少这样的结构:
state.allData = {
left: {
data: [ ... ]
},
right: {
data: [ ... ],
pins: [ ... ]
}
}
LeftContainerstate.allData.left
从 MainContainer作为 prop 接收并传递props.left.data
给 SearchableList,再次作为 prop。
RightContainerstate.allData.right
从 MainContainer作为 prop 接收并传递props.right.data
给 SelectableList 和props.right.pins
Map。
SelectableList 显示一个复选框以允许对其项目进行操作。每当对 SelectableList 组件的项目发生操作时,它可能会对 Map 引脚产生副作用。
我决定在 RightContainer 的状态中存储一个列表,该列表保留 SelectableList 显示的所有项目的 id;此列表作为props传递给 SelectableList 和 Map。然后我传递给 SelectableList 一个回调,每当进行选择时更新 RightContainer 内的 id 列表;新的 props 出现在 SelectableList 和 Map 中,因此render()
在两个组件中都会被调用。
它工作正常并有助于将 SelectableList 和 Map 可能发生的所有事情保留在 RightContainer 内,但我问这对于提升状态和单一来源的概念是否正确。
作为可行的替代方案,我想为MainContainer 中的_selected
每个项目添加一个属性state.right.data
,并将选择回调三个级别向下传递给 SelectableList,处理 MainContainer 中所有可能的操作。但是一旦发生选择事件,这最终将强制加载 LeftContainer 和 RightContainer,引入了实现逻辑的需要,例如shouldComponentUpdate()
避免无用,render()
尤其是在 LeftContainer 中。
从架构和性能的角度来看,哪个是/可能是优化此页面的最佳解决方案?
下面是我的组件的摘录,以帮助您了解情况。
主容器.js
class MainContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
allData: {}
};
}
componentDidMount() {
fetch( ... )
.then((res) => {
this.setState({
allData: res
});
});
}
render() {
return (
<div className="main-container">
<LeftContainer left={state.allData.left} />
<RightContainer right={state.allData.right} />
</div>
);
}
}
export default MainContainer;
RightContainer.js
class RightContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedItems: [ ... ]
};
}
onDataSelection(e) {
const itemId = e.target.id;
// ... handle itemId and selectedItems ...
}
render() {
return (
<div className="main-container">
<SelectableList
data={props.right.data}
onDataSelection={e => this.onDataSelection(e)}
selectedItems={this.state.selectedItems}
/>
<Map
pins={props.right.pins}
selectedItems={this.state.selectedItems}
/>
</div>
);
}
}
export default RightContainer;
提前致谢!