[英]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>
有很多不同的方法來處理這個問題,但這是一種對我來說似乎很有效的方法:
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.