我有一个MyList
获取项目的组件,允许过滤和排序。该组件已在应用程序的其他部分使用,并且运行良好。它使用渲染 Prop 来渲染项目,因此它接受 renderItem
类型函数的 prop。
现在我正在构建一个简单的列表,以允许使用上述组件进行项目选择,并且我正在检查渲染属性 renderItem
中的选定状态方法。问题是当我更改 MySelectableList
的状态时MyList
组件不会更新,因为它的 props 没有改变(它始终是相同的绑定(bind)函数 renderProp
)。现在我用 this.renderItem = this.renderItem.bind(this);
强制渲染 child 。但我不喜欢它,我知道我可以用 ref
更新子组件但我也不喜欢。
是否有更好的方法来强制子组件在父状态发生变化时渲染?我做错了什么吗?
完整代码MySelectableList
:
class MySelectableList extend Component {
constructor (props) {
super(props);
this.state = {
selectedItems: [],
};
this.renderItem = this.renderItem.bind(this);
this.toggle = this.toggle.bind(this);
this.isSelected = this.isSelected.bind(this);
}
toggle (item) {
const newItems = this.state.selectedItems.slice(0);
const index = newItems.indexOf(item.uuid);
if (index === -1) {
newItems.push(item.uuid);
} else {
newItems.splice(index, 1);
}
this.setState({ selectedItems: newItems });
// Force MyList to re-render by tricking react that it's different
this.renderItem = this.renderItem.bind(this);
}
isSelected (item) {
return this.state.selectedItems.includes(item.uuid);
}
renderItem (item) {
return (<MySelectableItem
key={ item.uuid }
item={ item }
toggle={ this.toggle }
selected={ this.isSelected(item) } />);
}
render () {
return (
<div>
...
<MyList renderItem={ this.renderItem } />
...
</div>
);
}
}
提前致谢。
编辑
MyList
组件使用 connect
连接到 redux store 。我发现connect
是 MyList
的原因组件缺少渲染,仅使用“vanilla” react 组件即可正常工作。
我在这个codesandbox中重现了这个问题:https://codesandbox.io/s/0mov14nmmp
最佳答案
既然您询问如何以更友好的方式做到这一点
更好的方法是:
render () {
return (
<div>
<MyList {...whateeverExtraPropsyouWantToPass}>
<MySelectableItem
key={ item.uuid }
item={ item }
toggle={ this.toggle }
selected={ this.isSelected(item) } />
</MyList>
</div>
);
然后你的 MyList 将如下所示:
render () {
return (
<div>
...//your other MyList code
...
{this.props.children}
</div>
);
这看起来更具可读性,更易于维护且易于调试。但我相信这对你来说都是显而易见的。既然您询问了 react 友好的方式
,这是您可以做到的最 react 友好的方式。
我不会建议不必要的、显式地尝试渲染任何组件。直到且除非这是唯一的方法,但您的组件中并非如此。
关于javascript - 当父状态改变时强制子组件更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48387872/