【问题标题】:React.js remove item from Array in state syntaxReact.js 以状态语法从数组中删除项目
【发布时间】:2020-09-01 14:54:28
【问题描述】:

我想使用 prevState 语法从数组 onClick 中删除一个项目。

这是我使用的示例代码:

export default function App() {
  const [selected, setSelected] = useState(false);
  const [selectedItems, setSelectedItems] = useState([]);
  const [cards, setCards] = useState(["card1", "card2", "card3", "card4"]);

  function handleButtonClick(event) {
    setSelected(true);
    let key = event.target.id;
    key = parseInt(key, 10);
    if (selectedItems.indexOf(key) === -1) {
      
      setSelectedItems([...selectedItems, key]);
    } else {
      //  HOW do i remove the item from the array ????
      let index = selectedItems.indexOf(key);
    }
  }

  return (
    <div className="App">
      {cards.map((card, index) => (
        <button
          className={
            selected && selectedItems.indexOf(index) !== -1
              ? "button1 active"
              : "button1"
          }
          onClick={handleButtonClick}
          id={index}
        >
          {card}
        </button>
      ))}
    </div>
  );
}

沙盒链接:https://codesandbox.io/s/patient-thunder-mb1vx?file=/src/App.js

【问题讨论】:

    标签: javascript arrays reactjs


    【解决方案1】:

    使用Array#splice的选项使用setState的函数形式:

    const [items, setItems] = React.useState([]);
    const deleteItemAtIndex = (index) => setItems(items => {
      const newItems = [...items];
      newItems.splice(index, 1);
      return newItems;
    });
    

    这样做的好处是它可以被记忆(useCallback)而不需要items作为依赖(因为setItems总是稳定的并且函数本身不使用items,只有回调使用) :

    const deleteItemAtIndex = React.useCallback((index) => setItems(items => {
      const newItems = [...items];
      newItems.splice(index, 1);
      return newItems;
    }), []);
    

    【讨论】:

      【解决方案2】:

      selectedItems 中找到键的索引后,通过在该索引之前和之后对数组进行切片来设置selectedItems 的状态:

      const index = selectedItems.indexOf(key);
      setSelectedItems([
        ...selectedItems.slice(0, index),
        ...selectedItems.slice(index + 1)
      ]);
      

      const { useState } = React;
      
      const App = () => {
        const [selected, setSelected] = useState(false);
        const [selectedItems, setSelectedItems] = useState([]);
        const [cards, setCards] = useState(["card1", "card2", "card3", "card4"]);
      
        function handleButtonClick(event) {
          setSelected(true);
          let key = event.target.id;
          key = parseInt(key, 10);
          if (selectedItems.indexOf(key) === -1) {
            let index = selectedItems.indexOf(key);
            setSelectedItems([...selectedItems, key]);
          } else {
            const index = selectedItems.indexOf(key);
            setSelectedItems([
              ...selectedItems.slice(0, index),
              ...selectedItems.slice(index + 1)
            ]);
          }
        }
      
        return (
          <div className="App">
            {cards.map((card, index) => (
              <button
                className={
                  selected && selectedItems.indexOf(index) !== -1
                    ? "button1 active"
                    : "button1"
                }
                onClick={handleButtonClick}
                id={index}
                key={index}
              >
                {card}
              </button>
            ))}
          </div>
        );
      }
      
      ReactDOM.render(<App />, document.querySelector('.react'));
      .App {
        font-family: sans-serif;
        text-align: center;
      }
      
      .active {
        border: 2px solid green;
      }
      <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 class="react"></div>

      还记得对列表使用唯一的key 属性,并尽可能使用prefer const 而非let

      【讨论】:

        【解决方案3】:

        使用这个。希望它会起作用。

        if (selectedItems.indexOf(key) === -1) {
          setSelectedItems([...selectedItems, key]);
        } else {
          //  HOW do i remove the item from the array ????
          let index = selectedItems.indexOf(key);
          const arr = selectedItems.filter((item, i) => i !== index);
          setSelectedItems(arr);
        }
        

        查看此链接https://codesandbox.io/s/stupefied-greider-m25le

        【讨论】:

          【解决方案4】:

          您可以制作数组的副本,从副本中拼接索引,然后使用新数组设置状态。

          const newArray = [...oldArray]
          newArray.splice(index, 1)
          setSelectedItems(newArray)
          

          【讨论】:

            【解决方案5】:

            使用splice 替代@CertainPerformance:

            const copy = [...selectedItems];
            const index = copy.indexOf(key);
            copy.splice(index, 1);
            setSelectedItems(copy);
            

            【讨论】:

              【解决方案6】:

              我觉得奇怪的是没有发布简单的标准答案:

              function handleButtonClick(event) {
                  setSelected(true);
                  const key = parseInt(event.target.id, 10);
                  setSelectedItems(selectedItems => {
                      const itemIndex = selectedItems.indexOf(key);
                      if (itemIndex === -1) {
                          // New item, add it
                          selectedItems = [...selectedItems, key];
                      } else {
                          // New item, add it
                          selectedItems = selectedItems.filter((_, index) => index !== itemIndex); // ***
                      }
                      return selectedItems;
                  });
              }
              

              请注意,由于这会根据现有状态设置状态,因此最好使用状态设置器的回调形式。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-07-19
                • 2021-04-03
                • 1970-01-01
                • 1970-01-01
                • 2021-03-10
                相关资源
                最近更新 更多