React setState 不适用于 if 语句

Posted

技术标签:

【中文标题】React setState 不适用于 if 语句【英文标题】:React setState doesn't work with if statement 【发布时间】:2021-09-28 00:01:04 【问题描述】:

我不明白为什么下面的代码不会改变状态。即使执行“if”语句,状态也是相同的。为什么if 的大小写不会改变状态?

class Welcome extends React.Component 
  state = 
    items: [
      
        id: 1,
        done: false,
      ,
      
        id: 2,
        done: false,
      ,
      
        id: 3,
        done: false,
      ,
    ]
  
  
  handleDone = (index) => 
      this.setState((prevState) => 
        const copyItems = [...prevState.items];

      if (copyItems[index].done === false) 
        console.log("Done should be true");
        copyItems[index].done = true;
       else 
        console.log("Done should be false");
        copyItems[index].done = false;
      

      // copyItems[index].done = !copyItems[index].done - the same result

      return 
        items: [...copyItems],
      ;
    );
  

  render() 
    return (
      this.state.items.map((item, index) => 
        return (
          <div>
            <span>id: item.id</span>
            <span> item.done ? "- is not done" : "- is done" </span>
            <button 
              onClick=() => this.handleDone(index)>
              Change to opposite
            </button>
          </div>
        )
      )
    )
  



ReactDOM.render(<Welcome />, document.body);
<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>
this.setState((prevState) => 
  const copyItems = [...prevState.items];

  if (copyItems[index].done === false) 
    console.log("Done should be true");
    copyItems[index].done = true;
   else 
    console.log("Done should be false");
    copyItems[index].done = false;
  

  // copyItems[index].done = !copyItems[index].done - the same result

  return 
    items: [...copyItems],
  ;
);

当没有if 语句时,以下示例可以正常工作:

this.setState((prevState) => 
  const copyItems = [...prevState.items];

  copyItems[index].done = true;
 
  return 
    items: [...copyItems],
  ;
);

在复制对象时,下面的示例可以很好地使用“if”语句:

this.setState((prevState) => 
  const copyItems = JSON.parse(JSON.stringify([...prevState.items]));

  copyItems[index].done = !copyItems[index].done

  return 
    items: [...copyItems],
  ;
);

【问题讨论】:

你能提供你的代码的sn-p吗? 我添加了 sn-p,它工作正常。问题是由 StrictMode 引起的 【参考方案1】:

问题是由使用 &lt;React.StrictMode&gt; 包装应用程序的 create-react-app 引起的。

要解决它,只需删除此包装标签。就是这样。 这是预期的行为,它应该有助于避免产品上的错误。更多详情React docs。

【讨论】:

删除本应有助于避免产品错误的内容听起来并不正确。 @cyberskunk ***.com/a/65167384/7399693 你的意思是什么?我知道&lt;React.StrictMode&gt; 是什么,并且处理双重调用的函数很烦人。但是,它确实有助于避免副作用。【参考方案2】:

React 的问题在于,即使你扩展了数组,其中的对象仍然被引用为状态中的对象。所以通过copyItems[index].done = true; 你实际上是在直接改变状态(this.state[index].done 也应该是真的)。为了避免这种情况,您可以采取的措施是在您的 prevState 上使用 .map,这样您就不会直接更新状态。

const state = [ done: true ];
const stateCopy = [...state];

const toFind = 0;

stateCopy[toFind].done = false;

console.log(stateCopy[toFind], state[toFind]); //  done: false  ,  done: false  /!\ state should not be updated at this point.

// good way of doing that might be by using prevState.items.map() and do your logic inside it

const stateUpdated = state.map((el, index) => 
  if (index === toFind) 
    return  done: !el.done 
  
  return el;
);

console.log(stateUpdated[toFind], state[toFind]) // state is not mutated, as expected

【讨论】:

以上是关于React setState 不适用于 if 语句的主要内容,如果未能解决你的问题,请参考以下文章

getCurrentPosition 中的 React-native-maps setState 不适用于我的 url API

React setState不会更新[重复]

Coffeescript - 单击后React setState不呈现

SetState 不适用于 listview.builder

为啥 If 语句不适用于 selenium 中的 for 循环

布尔值不适用于 If 语句(Javascript)