gpt4 book ai didi

javascript - ReactJS - 提升状态与保持本地状态

转载 作者:行者123 更新时间:2023-12-03 13:08:26 25 4
gpt4 key购买 nike

在我的公司,我们正在将 Web 应用程序的前端迁移到 ReactJS。我们正在使用 create-react-app (更新到 v16),没有 Redux。现在我被困在一个页面上,该页面的结构可以通过下图简化:

Page structure

三个组件(SearchableList、SelectableList 和 Map)显示的数据是通过 MainContainer 的 componentDidMount() 方法中的相同后端请求检索的。然后,该请求的结果存储在 MainContainer 的状态中,其结构或多或少如下所示:

state.allData = {
left: {
data: [ ... ]
},
right: {
data: [ ... ],
pins: [ ... ]
}
}

LeftContainer 从 MainContainer 接收作为 prop state.allData.left 并将 props.left.data 传递给 SearchableList,再次作为 prop。

RightContainer 从 MainContainer 接收 prop state.allData.right 并将 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 内,但我问这对于 lifting-state-upsingle- 是否正确事实来源概念。

作为可行的替代方案,我想到为 MainContainer 中的 state.right.data 中的每个项目添加 _selected 属性,并将 select 回调传递给 SelectableList 三级,处理MainContainer 中所有可能的操作。但是一旦发生选择事件,最终将强制加载 LeftContainer 和 RightContainer,从而需要实现诸如 shouldComponentUpdate() 之类的逻辑,以避免无用的 render()在LeftContainer 中。

从架构和性能的 Angular 来看,哪个是/可能是优化此页面的最佳解决方案?

下面摘录了我的部分内容,以帮助您了解情况。

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;

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;

提前致谢!

最佳答案

正如 React 文档所述

Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor.

There should be a single “source of truth” for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the top-down data flow.

Lifting state involves writing more “boilerplate” code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs. Since any state “lives” in some component and that component alone can change it, the surface area for bugs is greatly reduced. Additionally, you can implement any custom logic to reject or transform user input.

因此,本质上您需要将那些正在被 Siblings 组件使用的状态提升到树上。因此,您首先实现将 selectedItems 作为状态存储在 RightContainer 中是完全合理的,也是一个很好的方法,因为父级不需要知道这个 dataRightContainer 的两个 child 组件共享,并且这两个组件现在拥有单一事实来源。

根据你的问题:

As feasible alternative I thought of adding a _selected property to each item in state.right.data in MainContainer and pass the select callback three levels down to SelectableList, handling all the possible actions in MainContainer

我不同意这是比第一种更好的方法,因为您 MainContainer 不需要知道 selectedItems 或处理任何更新。 MainContainer 对这些状态没有做任何事情,只是将其传递下去。

考虑优化性能,您自己谈到实现shouldComponentUpdate,但您可以通过扩展 React.PureComponent 创建组件来避免这种情况。它本质上是通过对 stateprops 进行 shallow 比较来实现 shouldComponentUpdate

根据文档:

If your React component’s render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.

但是,如果多个深度嵌套的组件使用相同的数据,则使用 redux 并将该数据存储在 redux-state 中是有意义的。这样整个App就可以全局访问它,并且可以在不直接相关的组件之间共享。

例如考虑以下情况

const App = () => {
<Router>
<Route path="/" component={Home}/>
<Route path="/mypage" component={MyComp}/>
</Router>
}

现在,如果 Home 和 MyComp 都想要访问相同的数据。您可以通过 render prop 调用数据作为 App 中的 props 进行传递。然而,通过使用像

这样的 connect 函数将这两个组件连接到 Redux 状态就可以轻松完成
const mapStateToProps = (state) => {
return {
data: state.data
}
}

export connect(mapStateToProps)(Home);

MyComp 也类似。此外,还可以轻松配置更新相关信息的操作

此外,为您的应用程序配置 Redux 特别容易,您将能够在各个 reducer 中存储与相同事物相关的数据。通过这种方式,您也可以模块化您的应用程序数据

关于javascript - ReactJS - 提升状态与保持本地状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46594900/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com