[英]How to update react state properly
我是新来的反应者,我想问问更新状态的最佳方法是什么,我有一些代码。 我知道以下代码不正确,因为它直接设置了状态。
handlexxx = foo => {
const foos = [...this.state.foos];
const index = foos.indexOf(foo);
foos[index].bar = !foo.bar;
this.setState({ foos });
};
这两个代码下面哪个更好? 有人可以帮我解释一下!
handlexxx = foo => {
const foos = [...this.state.foos];
const index = foos.indexOf(foo);
foos[index] = { ...foo };
foos[index].bar = !foo.bar;
this.setState({ foos });
};
handlexxx = foo => {
const foos = [...this.state.foos];
const index = foos.indexOf(foo);
foos[index] = { ...foos[index] };
foos[index].bar = !foos[index].bar;
this.setState({ foos });
};
我的帐户被一些否决问题所困扰,有趣的是,即使我已经接受了答案,我也必须重新编辑它们。我不知道这样做的意义。这个Stackoverflow系统让我很沮丧。
现在,除了继续编辑我的问题外,我基本上无能为力,并且所有问题都已得到解答。 这是荒唐的 !!!
您应该使用Array.prototype.map()
方法,如下所示:
handlexxx = foo => {
const foos = this.state.foos.map(f => {
if(foo.id === f.id) return {...f, bar: !f.bar}; // assume that the element has an identifier id
return f;
})
this.setState({ foos });
};
简而言之,使用ternary operator
代替if-else
语句
handlexxx = foo => {
const foos = this.state.foos.map(f => foo.id === f.id ? {...f, bar: !f.bar} : f
this.setState({ foos });
};
即使对于复杂的嵌套对象,也可以避免变异的一种经典方法是使用JSON.parse(JSON.stringify(COMPLICATED_OBJECT))
。 这将返回没有引用原始对象的对象表示形式,因此您可以在不影响原始对象的情况下对副本进行突变:
var foos = [
{ id: 1, bar: false },
{ id: 2, bar: false },
{ id: 3, bar: false },
]
var foo = foos[0];
var _foos = JSON.parse(JSON.stringify(foos)).map(f => {
if (f.id === foo.id) f.bar = !foo.bar;
return f;
});
如果运行此命令,则会看到foos
不变,但_foos
已更新
归根结底,您可能需要考虑最容易阅读的解决方案,以及团队中其他开发人员最容易阅读的解决方案。 如果您必须在3年后再次使用此代码,则希望能够从页面上读取代码而不会刮花头。
由于您的foo
对象具有id
属性,因此最好使用.map
方法,并将其与扩展语法或Object.assign
混合使用,然后按照@NguyễnThanhTú的说明返回相关元素。 但是,如果要使用索引执行此操作,请参见以下示例。
您可以使用findIndex
,而不是indexOf
。 由于indexOf
只是寻找一个值,因此findIndex
接受一个函数。 查找项目的索引,映射数组,然后如果索引匹配,则执行更改(如果不匹配),则返回不相关的项目。
state = { foos: [ { id: 1, bar: true }, { id: 2, bar: false }, { id: 3, bar: false }, ], }; const foo = { id: 2, bar: false }; const handleState = foo => { const index = state.foos.findIndex(el => el.id === foo.id ); const newFoos = state.foos.map( ( foo, i ) => { if ( i !== index ) { return foo }; return { ...foo, bar: !foo.bar }; }) console.log( newFoos ); } handleState(foo);
第二个。 在这里,我们以一种棘手的方式使用Object.assign
。 代替映射数组,我们使用Object.assign
并使用其索引更改项目。
state = { foos: [ { id: 1, bar: true }, { id: 2, bar: false }, { id: 3, bar: false }, ], }; const foo = { id: 2, bar: false }; const handleState2 = foo => { const index = state.foos.findIndex(el => el.id === foo.id ); const newFoos = Object.assign( [], state.foos, { [index]: { ...foo, bar: !foo.bar } }); console.log( newFoos ); } handleState2(foo);
第三个。 没有索引,只有.map
并直接使用id
属性。 我们不需要在这里找到索引,我们只需要检查id
属性以找到正确的项目。
state = { foos: [ { id: 1, bar: true }, { id: 2, bar: false }, { id: 3, bar: false }, ], }; const foo = { id: 2, bar: false }; const handleState3 = foo => { const newFoos = state.foos.map( el => { if ( el.id !== foo.id ) { return el }; return { ...el, bar: !el.bar }; }) console.log( newFoos ); } handleState3( foo );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.