我有一个MyList
组件可以获取项目,允许过滤和排序。此组件已在应用程序的其他部分中使用,并且运行良好。它使用渲染道具来渲染项目,使其接受类型函数的renderItem
道具。
现在我正在构建一个简单的列表,允许使用上述组件选择项目,并且我正在检查渲染道具renderItem
方法中的选定状态。问题是,当我更改MySelectableList
的状态时,MyList
组件不会更新,因为它的props不会更改(它始终是相同的绑定函数renderProp
)。现在我强迫用this.renderItem = this.renderItem.bind(this);
渲染孩子,但我不喜欢它,我知道我可以用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商店。我发现connect
是MyList
组件缺失渲染的原因,只使用“vanilla”反应组件才能正常工作。
我在此代码框中重现了该问题:https://codesandbox.io/s/0mov14nmmp
答案 0 :(得分:1)
因为您询问了如何以更友好的方式做到这一点
更好的方法是:
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>
);
这看起来更易读,更易于维护且易于调试。但我相信这对你来说显而易见。因为,你问过a react friendly way
,这是你能做的最友善的反应方式。
我不会建议不必要的,显式尝试渲染任何组件。直到并且除非它是唯一的方式,但在您的组件中并非如此。
答案 1 :(得分:0)
实现MyList的方式没有任何问题。 React Native FlatList具有相同的模式。但是为什么你也不把项目作为属性传递给MyList,所以它就像
<MyList items={this.state. selectedItems} renderItem={this.renderItem} />
这样MyList将重新渲染,因为items属性发生了变化。还需要items属性,因为我假设在你的MyList组件中你需要做items.map函数吗?否则你怎么知道你需要渲染多少项呢?