簡體   English   中英

使 state 更新在 React 中更具可讀性

[英]Making state updates more readable in React

我正在通過制作一個簡單的待辦事項列表來練習 React,其中包含一個任務和一個計數器,以指示我需要執行多少次。

我想通過創建一個包含我想要更新的值的 object 來使 state 更新更具可讀性,而不僅僅是更新內聯的所有內容,這可能有點難以閱讀,至少對我來說。 但是,它沒有顯示項目名稱,或者單擊按鈕時計數器沒有增加。

這是代碼沙箱: https://codesandbox.io/s/todo-list-practice-5g45c?file=/src/index.js

Original approach:
   const duplicates = () => {
     if (!(input in items)) {
       setListItem({ ...items, [input]: 1 });
     } else {
       setListItem({ ...items, [input]: items[input] + 1 });
     }
   };

Refactored approach: 

  const checkDuplicate = () => {
    if (!(input in items)) {
      const newItem = {
        name: input,
        count: 1
      };
      setItems({ ...items, newItem });
    } else {
      setItems((items[input] += 1));
    }
  };

Button and ul

      <button
        onClick={() => {
          checkDuplicate();
        }}
      >
        add item
      </button>

      <ul>
        {Object.keys(items).map((el) => (
          <li>
            {el.name}: {items[el].count}
          </li>
        ))}
      </ul>

有很多不同的方法來處理這個問題,但這是一種對我來說似乎很有效的方法:

編輯 kind-rain-hlzwq

function Todo() {
  const [newItem, setNewItem] = useState("");
  const [items, setItems] = useState({});

  const handleAddItem = () => {
    const count = items[newItem] || 0;

    setItems({
      ...items,
      [newItem]: count + 1,
    });
  };

  return (
    <div>
      <input
        onChange={(event) => {
          setNewItem(event.target.value);
        }}
        value={newItem}
      />
      <button onClick={handleAddItem}>Add Item</button>
      <ul>
        {Object.entries(items).map(([item, count]) => {
          return (
            <li key={item}>
              {item}: {count}
            </li>
          );
        })}
      </ul>
    </div>
  );
}

我的代碼和你的代碼之間的大部分差異都是無關緊要的,只是個人喜好。 不過,我確實在您的checkDuplicate function 中看到了一些問題:

const checkDuplicate = () => {
  if (!(input in items)) {
    const newItem = {
      name: input,
      count: 1,
    };
    setItems({ ...items, newItem });
  } else {
    setItems((items[input] += 1));
  }
};

在這里,您使用setItems將其設置為 object,其中包含舊 object 中的所有內容,但添加了新的鍵/值對。 代碼中的鍵是newItem ,值是{ name: input, count: 1 }

我認為您不希望密鑰是newItem ,我認為您希望它是input ,或者至少是其他東西。

也許這個?

setItems({ ...items, [input]: newItem });

然后在你的else子句中,你有:

setItems((items[input] += 1));

這將調用setItems的返回值為(items[input] += 1) ,這幾乎肯定不是您想要的。 相反,我認為您想在 if 子句中做與您在if子句中所做的基本相同的事情,而只是增加具有重復key的那個的計數。

也許這個?

setItems({
  ...items,
  [input]: {
    ...items[input],
    count: items[input].count + 1,
  },
});

還有其他方法可以做這種事情,但重要的是當你增加count時不要改變items 您需要構建一個全新的 object ,其中包括遞增的count

最后,如果您查看我的代碼的<li> ,您會看到我添加了一個key道具。 這不是您的問題,但是當您在列表上 map 以像您正在做的那樣生成 JSX 時,值得閱讀並包含在您的代碼中。 在此處閱讀有關 React 鍵和列表的信息

絕對要對我的代碼持保留態度。 我無法訪問您的所有代碼,因此我快速整理了一些內容以幫助您解除阻止。 我遺漏了您擁有的一些東西,例如您的項目 object 中的name鍵。

祝你好運!

import ReactDOM from "react-dom";
import React, { useState } from "react";

// TODO: build a todo app which can:
//  1. add items to a list (render below input)
//  2. iterate a counter next to each item

// We should use arrays for this use case, there's no restriction of using plain object
const Todo = () => {
  const [items, setItems] = useState([]);
  const [input, setInput] = useState("");

  const checkDuplicate = () => {
    const index = items.findIndex((item) => item.name === input);

    // if the item is already in array we get its index
    if (index !== -1) {
      const newArr = [...items];
      newArr[index].count += 1;
      return setItems(newArr);
    }

    // if the item is not in an array already we append it
    setItems([
      ...items,
      {
        name: input,
        count: 1
      }
    ]);
  };

  return (
    <div>
      <h1>TODO LIST</h1>
      <input value={input} onChange={(e) => setInput(e.target.value)} />
      <button
        onClick={() => {
          checkDuplicate();
        }}
      >
        add item
      </button>
      <ul>
        {items.map((el) => (
          <li>
            {el.name}: {el.count}
          </li>
        ))}
      </ul>
    </div>
  );
};
ReactDOM.render(<Todo />, document.getElementById("root"));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM