React setState 改变不同状态变量中所有对象的值

问题描述 投票:0回答:1

这是我的代码:

import "./styles.css";
import { useState } from "react";


export default function App() {
  const [input, setInput] = useState("")
  const [list, setList] = useState([
    {key:584535, value:"Do laundry", isChecked: false},
    {key:439735, value:"Take out trash", isChecked: false},
    {key:589774, value:"Do dishes", isChecked: true},
    {key:573735, value:"code", isChecked: false},
    {key:589739, value:"margin", isChecked: false},
    {key:585735, value:"textbox", isChecked: false}]
    )
  const [history, setHistory] = useState([[]])
  function handleCheckClick(e) {    
    let checkkey = e.target.getAttribute("checkboxkey")
    setHistory([...history, list])
    list.map(
      (element) => {
        if(element.key == checkkey){
          element.isChecked = !(element.isChecked)
        }
      }
    )
    setList([...list])
  }
  function handleRemoveClick(e) {
    let buttonKey = e.target.getAttribute("buttonkey") 
    list.forEach(
      (element, index) => {
        if(element.key == buttonKey){
          setHistory([...history, list])
          setList(list.toSpliced(index, 1))
        }
      }
    )
  }
  function handleSubmit() {
    if(input == ""){return}
    let key = Math.floor(100000 + Math.random() * 900000)
      setHistory([...history, list])
      setList([...list, {key: key, value: input, isChecked:false}]) 
      setInput("")
  }
  function handleHistoryClick(){
    if((history[history.length-1]) == undefined){return}
    setList(history.pop())
    setHistory([...history])
  }
  return (
    <div className="App">
      <h1>To Do</h1>
      <input id="input" type="text" value={input} onChange={(e) => setInput(e.target.value)}></input>
      <button onClick={handleSubmit}>Submit</button>
      <button onClick={handleHistoryClick}>Undo</button>
      <div id="container">
        <ol>
          {list.map(({key, value, isChecked}) =>
            <>
              {isChecked === true && <li id="strike" key={key}>{value}</li>}
              {isChecked === false && <li key={key}>{value}</li>}
              <input type="checkbox" checkboxkey={key} onClick={handleCheckClick}></input>
              <button buttonkey={key} onClick={handleRemoveClick}>Remove</button>
              <br />
           </>)
          }
        </ol>
      </div>
    </div>
  );
}

我有一个历史数组,它保存对主列表数组所做的所有更改的副本。当我尝试使用 list.map 中的

element.isChecked = !(element.isChecked)
将 isClicked 值分配给主数组时,它会更改所有历史数组中的值!这是每次使用“文本框”值切换复选框时 console.log 历史记录时的控制台图像,最后一次单击是将其设置为单击:Console.log of history

reactjs arrays setstate
1个回答
0
投票

JavaScript 中的对象是引用。因此,当两个数组引用相同的对象时,改变一个数组中的对象将影响另一个数组中的对象。因为对于任何给定的实例,只有一个对象,它只是被多个数组/变量/等引用。

鉴于这是 React 代码,这里简单的教训是不要改变 React 中的状态。这就是这行代码的作用:

element.isChecked = !(element.isChecked)

(此外,这是对

.map()
函数的误用,逻辑上
.forEach()
或循环更合适。)

相反,在更新状态时将数组投影到新对象的新数组中。例如:

setHistory([...history, list]);
setList(list.map(
  (element) => {
    if(element.key == checkkey) {
      return { ...element, isChecked = !element.isChecked };
    } else {
      return element;
    }
  }
));

这里的主要区别是

.map()
的回调返回的内容。如果“key”匹配,它将返回一个从现有对象加上一个修改后的属性构建的新对象。否则,它按原样返回对象。因此,任何需要更改的对象都会产生一个新对象,而不是改变现有对象。

© www.soinside.com 2019 - 2024. All rights reserved.