如何正确更新反应状态

时间:2018-10-04 00:40:24

标签: javascript reactjs

我是新来的反应者,我想问问更新状态的最佳方法是什么,我有一些代码。我知道以下代码不正确,因为它直接设置了状态。

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系统。

现在,除了继续编辑我的问题外,我基本上无能为力,并且所有问题都已得到解答。这太荒谬了!!!

3 个答案:

答案 0 :(得分:1)

您应使用const createGroupedArray = (arr, size) => arr.reduce((result, item) => { if (result.length && result[result.length - 1].length < size) { result[result.length - 1].push(item); } else { result.push([item]); } return result; }, []); console.log(createGroupedArray([1,2,3,4,5],2)); console.log(createGroupedArray([1,2,3],1)); const testCreateGroupedArray = (arr, size) => { const result = createGroupedArray(arr, size); const resultSizeSuccess = result.length === (Math.floor(arr.length / size) + arr.length % size); const resultLastItemSizeSuccess = result[result.length - 1].length === (arr.length % size); return resultSizeSuccess && resultLastItemSizeSuccess; } console.log(testCreateGroupedArray([1,2,3,4,5],2)); console.log(testCreateGroupedArray([1,2,3],1));方法,如下所示:

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

答案 1 :(得分:1)

即使对于复杂的嵌套对象,避免变异的一种经典方法是使用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年内重新使用此代码,则希望能够从页面上读取该代码而不会刮花头。

答案 2 :(得分:0)

由于您的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 );