Luc*_*ioB 19 javascript reactjs create-react-app
在我的公司,我们正在将Web应用程序的前端迁移到ReactJS.我们正在使用create-react-app(更新到v16),没有Redux.现在我停留在一个页面上,可以通过以下图像简化结构:
在componentDidMount()MainContainer 的方法中使用相同的后端请求检索由三个组件(SearchableList,SelectableList和Map)显示的数据.然后,此请求的结果将存储在MainContainer的状态中,并且具有或多或少的结构:
state.allData = {
left: {
data: [ ... ]
},
right: {
data: [ ... ],
pins: [ ... ]
}
}
Run Code Online (Sandbox Code Playgroud)
LeftContainer state.allData.left从MainContainer 接收作为prop ,并props.left.data再次传递给SearchableList作为prop.
RightContainer state.allData.right从MainContainer 接收作为prop ,并传递props.right.data给SelectableList和props.right.pinsMap.
SelectableList显示一个复选框以允许对其项目执行操作.每当在SelectableList组件的项目上发生动作时,它可能对Map引脚有副作用.
我决定在RightContainer状态下存储一个列表,该列表保留SelectableList显示的所有项目ID; 此列表作为道具传递给SelectableList和Map.然后我向SelectableList传递一个回调函数,无论何时进行选择都会更新RightContainer中的id列表; 新的道具到达SelectableList和Map,因此render()在两个组件中都会调用.
它工作正常,有助于保持RightContainer中SelectableList和Map可能发生的一切,但我问这是否适用于提升状态和单一来源的概念.
作为可行的替代方案,我想到为MainContainer中的_selected每个项添加一个属性state.right.data,并将select回调三个级别传递给SelectableList,处理MainContainer中的所有可能操作.但是一旦选择事件发生,这将最终强制加载LeftContainer和RightContainer,引入了实现逻辑的需要,shouldComponentUpdate()以避免无用,render()特别是在LeftContainer中.
从架构和性能的角度来看,哪个/可能是优化此页面的最佳解决方案?
下面是我的组件摘录,以帮助您了解情况.
MainContainer.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;
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
提前致谢!
Shu*_*tri 10
正如React docs所述
通常,有几个组件需要反映相同的变化数据.我们建议将共享状态提升到最近的共同祖先.
对于在React应用程序中发生变化的任何数据,应该有一个"真实来源".通常,首先将状态添加到需要渲染的组件中.然后,如果其他组件也需要它,您可以将它提升到最近的共同祖先.您应该依赖自上而下的数据流,而不是尝试在不同组件之间同步状态.
提升状态涉及编写比双向绑定方法更多的"样板"代码,但作为一项好处,查找和隔离错误所需的工作量更少.由于任何一个状态"存在"某个组件中,并且该组件单独可以改变它,因此大大减少了错误的表面积.此外,您可以实现任何自定义逻辑来拒绝或转换用户输入.
所以基本上你需要提升那些正在用尽兄弟姐妹组件的树状态.所以你首先实现将你selectedItems作为一个状态存储在RightContainer完全合理和一个好的方法,因为父母不需要知道,这data是由两个child组件共享,而这两个组件RightContainer现在只有一个来源真相.
根据你的问题:
作为可行的替代方案,我想到为in
state.right.data中的每个项添加一个_selected属性MainContainer,并将select回调三个级别传递给SelectableList,处理所有可能的操作MainContainer
我不同意这是比第一个更好的方法,因为您MainContainer不需要知道selectedItems或处理任何更新.MainContainer对这些国家没有做任何事情,只是把它传下来.
考虑一下optimise on performance,你自己谈论实现a shouldComponentUpdate,但是你可以通过扩展来创建你的组件来避免这种情况,React.PureComponent这实际上是shouldComponentUpdate通过shallow比较state和来实现的props.
根据文件:
如果React组件的
render()函数在给定相同的props和state的React.PureComponen情况下呈现相同的结果,则在某些情况下可以使用t来提高性能.
但是,如果多个深度嵌套的组件正在使用相同的数据,那么使用redux并将该数据存储在redux-state中是有意义的.通过这种方式,整个App可以全局访问,并且可以在不直接相关的组件之间共享.
例如,考虑以下情况
const App = () => {
<Router>
<Route path="/" component={Home}/>
<Route path="/mypage" component={MyComp}/>
</Router>
}
Run Code Online (Sandbox Code Playgroud)
现在,如果Home和MyComp都想访问相同的数据.您可以通过renderprop 调用数据作为道具从App传递.但是,通过使用类似connect函数将这两个组件连接到Redux状态可以很容易地完成
const mapStateToProps = (state) => {
return {
data: state.data
}
}
export connect(mapStateToProps)(Home);
Run Code Online (Sandbox Code Playgroud)
并且类似地MyComp.此外,它还可以轻松配置更新相关信息的操作
此外,它还特别容易为您的应用程序配置Redux,并且您可以在各个Reducer中存储与相同内容相关的数据.通过这种方式,您也可以将应用程序数据模块化
我对此有诚实的建议.从经验来看:
Redux很简单.它很容易理解和扩展但是你应该将Redux用于某些特定的用例.
由于Redux封装了您的应用程序,您可以考虑存储以下内容:
你需要在全球范围内的东西.react-redux甚至允许组件上的@connect装饰器.所以喜欢:
@connect(state => ({
locale: state.locale,
currentUser: state.currentUser
}))
class App extends React.Component
Run Code Online (Sandbox Code Playgroud)
这些都作为道具传递下来,连接可以在应用程序的任何地方使用.虽然我建议只使用spread运算符传递全局道具
<Navbar {...this.props} />
Run Code Online (Sandbox Code Playgroud)
应用程序内的所有其他组件(或"页面")都可以执行自己的封装状态.例如,"用户"页面可以自己做.
class Users extends React.Component {
constructor(props) {
super(props);
this.state = {
loadingUsers: false,
users: [],
};
}
......
Run Code Online (Sandbox Code Playgroud)
您可以通过props访问locale和currentUser,因为它们是从Container组件传递下来的.
这种方法我多次完成它并且它可以工作.
但是,既然您想要首先整合React的知识,那么在执行Redux之前,您可以将您的状态存储在顶级组件上并将其传递给子级.
缺点:
这些缺点有点无聊且管理起来很麻烦.这就是Redux建成的原因.
希望我帮忙.祝好运
| 归档时间: |
|
| 查看次数: |
6606 次 |
| 最近记录: |