如何在反应状态下使用索引更新对象?

时间:2020-09-26 18:07:53

标签: reactjs

假设我有一个类似的数组

[
  { id: 1, name: "John" , selected: true}
  { id: 2, name: "Jim" , selected: false }
  { id: 3, name: "James" , selected: false }
]

我具有获取ID的函数,并希望基于该ID将对象的selected属性更改为true,并将其他selected属性对象更改为false

这是我尝试过的功能,但它抛出错误

const handleOnClick = (id) => {
     const temps = state.findIndex((sub) => sub.id === id)
        setState(prevState => ({
            ...prevState,
            [prevState[temps].selected]: !prevState[temps].selected
        }))

1 个答案:

答案 0 :(得分:2)

使用.map()迭代所有内容。如果不重新创建树到更改的对象,则不应更改数组中的值。参见下面的示例。

在下面,您将:

    在每个元素上
  1. map
  2. 传播其当前值
  3. 根据selected是否是新选择的id来覆盖id

我还提供了一个附加功能来使用数组中项目的索引而不是id进行更新,因为您的标题是“如何在反应状态下使用索引来更新对象?”,尽管您的问题也提到了改变id。我会说如果您有选择,请按id进行操作,数组索引可以更改。

const App = () => {
  const [state, setState] = React.useState([
    { id: 1, name: "John" , selected: true},
    { id: 2, name: "Jim" , selected: false },
    { id: 3, name: "James" , selected: false }
  ]);

  // This takes the ID of the item
  const handleOnClick = (id) => {
    const newState = state.map(item => {
      return {
        ...item,
        selected: item.id === id
      };
    });
    
    setState(newState);
  };
  
  // This takes the index of the item in the array
  const handleOnClickByIndex = (indexToSelect) => {
    const newState = state.map((item, idx) => {
      return {
        ...item,
        selected: indexToSelect === idx
      };
    });
    
    setState(newState);
  };
        
  return (
    <div>
      {state.map((item, mapIndex) => (
        <div key={item.id}>
          <div>
            <span>{item.name} is selected: {item.selected ? "yes" : "no"}</span>
            {/* This will update by ID*/}
            <button onClick={() => handleOnClick(item.id)}>Select using ID</button>
            {/* This will update by the index of the array (supplied by map) */}
            <button onClick={() => handleOnClickByIndex(mapIndex)}>Select using index</button>
          </div>
        </div>
      ))}
    </div>
  );
};

ReactDOM.render(
  <App/>,
  document.getElementById("app")
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="app"></div>