反应:从渲染方法外部更新组件的 props,而不使用状态
React: update component's props from outside of render method without using state
这就是我想要实现的目标。我有两个 React 组件Product
和 ProductInfoPanel
,显示在一个ProductList
组件中。 Product
显示有关产品的选定信息,例如产品名称和价格。单击产品时,更多详细信息将显示在ProductInfoPanel
中。所以我需要通过哇哇点击到ProductInfoPanel
.
这是我目前将它们连接在一起的方式。每个Product
都会得到一个点击处理程序,该处理程序在调用时传回product
对象,然后将其传递到ProductInfoPanel
的 props 中。ProductList
使用状态来跟踪单击的内容,因此当它发生变化时,它会触发信息面板的重新呈现。
class ProductList extends React.Component {
render() {
return (
<div>
<div className='content'>
<ul>
{ this.props.products.map((product, index) => {
return (
<li key={index}>
<Product product={product}
clickHandler={this.onProductClicked.bind(this)}/>
</li>
);
})}
</ul>
</div>
<div className='side-panel'>
<ProductInfoPanel product={this.state.selectedProduct} />
</div>
</div>
);
}
onProductClicked(clickedProduct) {
// Use the product object that was clicked, and updates the state.
// This updates the info panel content.
this.setState({ selectedProduct: clickedProduct });
}
}
以下是这两个组件的大致构造方式。
class Product extends React.Component {
render() {
// Even though it needs only name and price, it gets the whole product
// object passed in so that it can pass it to the info panel in the
// click handler.
return (
<div onClick={this.onClicked.bind(this)}>
<span>{this.props.product.name}</span>
<span>{this.props.product.price}</span>
</div>
);
}
onClicked(e) {
this.props.clickHandler(this.props.product);
}
}
class ProductInfoPanel extends React.Component {
render() {
// Info panel displays more information about a product.
return (
<ul>
<li>{this.props.product.name}</li>
<li>{this.props.product.price}</li>
<li>{this.props.product.description}</li>
<li>{this.props.product.rating}</li>
<li>{this.props.product.review}</li>
</ul>
);
}
}
这是我能想到的最好的,但是使用状态来跟踪点击的产品对我来说仍然听起来是错误的。我的意思是,这不是一个组件的真正状态,是吗?
如果我可以从 render
方法外部更新引用的 React 组件的props
,那么我会尝试将对每个Product
ProductInfoPanel
的引用传递给每个 ,以便他们可以在他们的点击处理程序中更新它。
有没有办法实现我想要的并避免使用状态来跟踪点击的内容?
你可以使用像 redux 这样的类似 flux 的库,或者像 mobx 这样的替代方案来从组件中删除状态管理,但我个人的感觉是保持它尽可能简单,直到你真的觉得在你的项目中添加另一个抽象层会有显着的好处。
我曾经默认使用 redux 开始项目,但有一次我踢了自己,因为事实证明,引入 redux 实现的额外复杂性对于实际上相当小而简单的项目来说是矫枉过正的。 我不知道是否有一条很难知道什么时候你应该回避使用标准状态并引入另一个库来为你管理它,但我已经了解到,首先以最简单和最简单的方式做这件事可能是最安全的,直到你真正觉得引入另一个依赖项有实际好处。
关于您当前代码的一些建议...
您将函数绑定在属性中,如下所示:
<Product product={product} clickHandler={this.onProductClicked.bind(this)}/>
当你调用函数bind
它实际上返回一个新的函数实例时,因此 React 的协调器会将其视为进入组件的新 prop,因此将始终重新渲染子组件树。 需要注意的事情。 作为替代方法,您可以在构造函数中进行早期绑定,如下所示:
class ProductList extends React.Component {
constructor(props) {
super(props);
this.onProductClicked = this.onProductClicked.bind(this);
}
render() {
...
<li key={index}>
<Product product={product}
clickHandler={this.onProductClicked}/>
</li>
...
}
}
此外,如果您提供index
,因为它们是上面唯一key
道具 - 您应该考虑使用product
模型中的唯一标识符(如果可用)。 这样,如果你在列表中添加或删除项目,React 将有更多的信息来知道它是否应该重新渲染所有Product
组件实例。
例如:
render() {
...
{
this.props.products.map((product) =>
<li key={product.id}>
<Product product={product}
clickHandler={this.onProductClicked}/>
</li>
)
}
...
}
在此处阅读有关这些概念的更多信息:https://facebook.github.io/react/docs/advanced-performance.html
我认为这很好。如果有更多的组件响应SelectedProduct
的变化,那么让父组件控制状态的价值将更加明显。在您的情况下,这似乎没有必要,因为只有一个组件更改。
但是,如果您的Product
也通过突出显示SelectedProduct
来响应,并且RecentlyViewedProducts
列表以某种方式响应SelectedProduct
,那么很明显,SelectedProduct
不是ProductInfoPanel
的状态,而是它是观察者的应用程序的更高级别部分的状态。
- 事件和状态
- 获取选择框的状态
- 相位器状态未捕获参考错误
- 如何更改reactjs中外部/独立组件的状态或属性
- 如何使用密码检测网络中的状态连接
- Ember.js-接口状态应该存储在哪里
- 混合 ui-sref 和 $state.go 在 Angular ui-router 中进行状态转换
- 在Angular 2中布线期间保持零部件处于活动状态
- 在mvc应用程序中,在回发时保留最初隐藏的文本框的隐藏或可见状态
- 可能的 React Antipattern:从 props 设置初始状态
- 从props中初始化组件状态
- 通过props来初始化子组件的状态是否正确?
- 在React子组件上使用props更新状态
- 当props通过parent状态更新时,React - child不更新
- 访问与Redux状态数据一起发送给组件的props
- 如何在 reactjs 中设置单个单击事件的状态和 props
- 反应:从渲染方法外部更新组件的 props,而不使用状态
- React Redux 将状态作为 props 传递给组件
- ReactJS:通过props改变父节点的子节点状态
- 如何将props(状态和函数)传递给子路由器组件