- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我的公司,我们正在将 Web 应用程序的前端迁移到 ReactJS。我们正在使用 create-react-app (更新到 v16),没有 Redux。现在我被困在一个页面上,该页面的结构可以通过下图简化:
三个组件(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-up 和 single- 是否正确事实来源概念。
作为可行的替代方案,我想到为 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
中是完全合理的,也是一个很好的方法,因为父级不需要知道这个 data
由 RightContainer
的两个 child
组件共享,并且这两个组件现在拥有单一事实来源。
根据你的问题:
As feasible alternative I thought of adding a _selected property to each item in
state.right.data
inMainContainer
and pass the select callback three levels down toSelectableList
, handling all the possible actions inMainContainer
我不同意这是比第一种更好的方法,因为您 MainContainer
不需要知道 selectedItems
或处理任何更新。 MainContainer
对这些状态没有做任何事情,只是将其传递下去。
考虑优化性能
,您自己谈到实现shouldComponentUpdate
,但您可以通过扩展 React.PureComponent
创建组件来避免这种情况。它本质上是通过对 state
和 props
进行 shallow
比较来实现 shouldComponentUpdate
。
根据文档:
If your React component’s
render()
function renders the same result given the same props and state, you can useReact.PureComponen
t 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/
我正在通读 Windows Phone 7.5 Unleashed,有很多代码看起来像这样(在页面的代码隐藏中): bool loaded; protected override void OnNav
在cgi服务器中,我这样返回 print ('Status: 201 Created') print ('Content-Type: text/html') print ('Location: htt
我正在查看 esh(easy shell)的实现,无法理解在这种情况下什么是 22 和 9 信号。理想情况下,有一个更具描述性的常量,但我找不到列表。 最佳答案 信号列表及其编号(包括您看到的这两个)
我的Oozie Hive Action 永远处于运行模式。 oozie.log文件中没有显示错误。
我正在编写一个使用 RFCOMM 通过蓝牙连接到设备的 Android 应用程序。我使用 BluetoothChat 示例作为建立连接的基础,大部分时间一切正常。 但是,有时由于出现套接字已打开的消息
我有一个云调度程序作业,它应该每小时访问我的 API 以更新一些价格。这些作业大约需要 80 秒才能运行。 这是它的作用: POST https://www.example.com/api/jobs/
我正在 Tomcat 上访问一个简单的 JSP 页面: 但是当我使用 curl 测试此页面时,我得到了 200 响应代码而不是预期的 202: $ curl -i "http://localhos
有时 JAR-RS 客户端会发送错误的语法请求正文。服务器应响应 HTTP status 400 (Bad Request) , 但它以 HTTP status 500 (Internal Serve
我正在尝试通过 response.send() 发送一个整数,但我不断收到此错误 express deprecated res.send(status): Use res.sendStatus(sta
我已经用 Excel 和 Java 做过很多次了……这次我需要用 Stata 来做,因为保存变量更方便'labels .如何将 dataset_1 重组为下面的 dataset_2? 我需要转换以下
我正在创建一个应用程序,其中的对象具有状态查找功能。为了提供一些上下文,让我们使用以下示例。 帮助台应用程序,其中创建作业并通过以下工作流程移动: 新 - 工作已创建但未分配 进行中 - 分配给工作人
我想在 Keras 中运行 LSTM 并获得输出和状态。在 TF 中有这样的事情 with tf.variable_scope("RNN"): for time_step in range
有谁知道 Scala-GWT 的当前状态 项目? 那里的主要作者 Grzegorz Kossakowski 似乎退出了这个项目,在 Spring 中从事 scalac 的工作。 但是,在 interv
我正在尝试编写一个 super 简单的 applescript 来启动 OneDrive App , 或确保打开,当机器的电源设置为插入时,将退出,或确保关闭,当电源设置为电池时。 我无法找到如何访问
目前我正在做这样的事情 link.on('click', function () { if (link.attr('href') !== $route.current.originalPath
是否可以仅通过查看用户代理来检测浏览器上是否启用/禁用 Javascript。 如果是,我应该寻找什么。如果否,检测用户浏览器是否启用/禁用 JavaScript 的最佳方法是什么 最佳答案 不,没有
Spring 和 OSGi 目前的开发状况如何? 最近好像有点安静了。 文档的最新版本 ( http://docs.spring.io/osgi/ ) 来自 2009 年。 我看到一些声明 Sprin
我正在从主函数为此类创建一个线程,但即使使用 Thread.currentThread().interrupt() 中断它,输出仍然包含“Still Here”行。 public class Writ
为了满足并发要求,我想知道如何在 Godog 中的多个步骤之间传递参数或状态。 func FeatureContext(s *godog.Suite) { // This step is ca
我有一个UIButton子类,它不使用UIImage背景,仅使用背景色。我注意到的一件事是,当您设置按钮的背景图像时,有一个默认的突出显示状态,当按下按钮时,该按钮会稍微变暗。 这是我当前的代码。
我是一名优秀的程序员,十分优秀!