React:如何在没有索引或唯一标识符的情况下修改基于数组的状态?
React: How to modify an array-based state, without an index or a unique identifier?
假设我有一个选项卡式组件。每个选项卡都代表一个人对象。用户可以切换活动选项卡,修改或删除每个选项卡,甚至更改它们的顺序:
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、索引或任何其他"identifier",这使得代码比它需要的复杂得多成为?
对于那些熟悉 VueJS 和 Angular 的人来说,我相信你知道修改对象是多么容易,因为你不需要 return 一个新的状态树每一个变化。
如果要更改数组的顺序,则在渲染时不能依赖数组 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>
假设我有一个选项卡式组件。每个选项卡都代表一个人对象。用户可以切换活动选项卡,修改或删除每个选项卡,甚至更改它们的顺序:
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、索引或任何其他"identifier",这使得代码比它需要的复杂得多成为?
对于那些熟悉 VueJS 和 Angular 的人来说,我相信你知道修改对象是多么容易,因为你不需要 return 一个新的状态树每一个变化。
如果要更改数组的顺序,则在渲染时不能依赖数组 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>