假设我有一个选项卡式组件。每个选项卡均显示一个人员对象。用户可以切换活动标签,修改或删除每个标签,甚至更改其顺序:
state={
activeTab:0,
tabs:[
{
name:'John',
age:34
},
{
name:'Bob',
age:31
},
]
}
假设我要修改特定选项卡(人)的字段之一。我可以使用此功能:
modifyTab = (index, prop, value) => {
const tabs = [...this.state.tabs];
const tab = tabs[index];
tab[prop] = value;
this.setState({ tabs })
}
这个问题是,它依赖于给定标签的索引。但是,如果选项卡索引发生了变化(如果我提供的话),可以切换选项卡的顺序呢?(就像浏览器为它们的选项卡所做的那样)。
或者如果我需要为异步操作注册一些回调,当相关人员坐在另一个选项卡中时可能会调用该回调(也许在调用回调时,选项卡已从1移至0 )?
是否有任何方法可以仅依靠对象引用而与id,索引或任何其他“标识符”无关,这会使代码变得比所需复杂得多。
对于那些熟悉VueJS和Angular的人,我确定您知道修改对象是多么容易,因为您无需在每次更改时都返回新的状态树。
答案 0 :(得分:3)
如果要更改数组的顺序,则在渲染时,不能依赖数组index
作为key
道具。解决此问题的一种常见方法是向数组中的每个对象添加唯一属性,然后使用该属性,例如id
。
将整个对象引用传递给modifyTab
会很好。您可以使用简单的indexOf
找出数组中的哪个对象。
示例
class App extends React.Component {
state = {
tabs: [
{
name: "John",
age: 34,
id: 1
},
{
name: "Bob",
age: 31,
id: 2
}
]
};
modifyTab = (tab, prop, value) => {
this.setState(prevState => {
const tabs = [...prevState.tabs];
const index = tabs.indexOf(tab);
tabs[index] = { ...tabs[index], [prop]: value };
return { tabs };
});
};
render() {
return (
<div>
{this.state.tabs.map(tab => (
<span
key={tab.id}
onClick={() => this.modifyTab(tab, "name", Math.random())}
style={{ margin: '0 10px' }}
>
{tab.name}
</span>
))}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>