我有一個代碼,我將它傳遞給onClick事件,我希望它運行 3 次:(此代碼基本上從產品中隨機選擇一個產品,然后通過 Hooks 我更新狀態以將其顯示在購物車中,實際上在這里而不是我打算展示 3 個隨機產品。所以我在想有沒有辦法一鍵觸發onClick 3 次。)
const onRandom = () => {
const randomItem = products[Math.floor(Math.random() * products.length)];
const exist = cartItems.find((x) => x.id === randomItem.id);
if (exist) {
setCartItems(
cartItems.map((x) =>
x.id === randomItem.id ? { ...exist, qty: exist.qty 1 } : x
)
);
} else {
setCartItems([...cartItems, { ...randomItem, qty: 1 }]);
}
};
我用過無數種方法,但似乎沒有一種方法有效......
const onRandom = () => {
const randomItem = products[Math.floor(Math.random() * products.length)];
const exist = cartItems.find((x) => x.id === randomItem.id);
if (exist) {
setCartItems(
cartItems.map((x) =>
x.id === randomItem.id ? { ...exist, qty: exist.qty 1 } : x
)
);
} else {
setCartItems([...cartItems, { ...randomItem, qty: 1 }]);
}
onRandom2();
};
const onRandom2 = () => {
const randomItem2 = products[Math.floor(Math.random() * products.length)];
const exist2 = cartItems.find((x) => x.id === randomItem2.id);
if (exist2) {
setCartItems(
cartItems.map((x) =>
x.id === randomItem2.id ? { ...exist2, qty: exist2.qty 1 } : x
)
);
} else {
setCartItems([...cartItems, { ...randomItem2, qty: 1 }]);
}
};
我還使用了for和while并將const更改為var,但我仍然得到一個隨機產品,甚至沒有錯誤。
也許我錯過了一些關于狀態含義的東西。
uj5u.com熱心網友回復:
讓我用一個簡單的例子來演示這個問題:
function App() {
const [counter, setCounter] = React.useState(0);
// Only adds 1 per click because counter stays the same (you
// are working with an outdated counter). So you are simply
// setting it 3 times to an increment of 1 using the same outdated
// value for all 3 increments.
function add3() {
setCounter(counter 1); // setCounter(0 1);
setCounter(counter 1); // setCounter(0 1);
setCounter(counter 1); // setCounter(0 1);
}
// Does add 3 per click because the counter passed to
// the callback is the updated version.
function add3Functional() {
setCounter(counter => counter 1); // setCounter(0 1);
setCounter(counter => counter 1); // setCounter(1 2);
setCounter(counter => counter 1); // setCounter(2 3);
}
return (
<div>
{counter}
<button onClick={add3}>add 3 (non-functional)</button>
<button onClick={add3Functional}>add 3 (functional)</button>
</div>
);
}
ReactDOM.render(<App />, document.querySelector("#root"));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
這是相關的 React 檔案:
功能更新
如果使用先前的狀態計算新狀態,則可以將函式傳遞給
setState。該函式將接收先前的值,并回傳一個更新的值。這是一個使用兩種形式的計數器組件的示例setState:function Counter({initialCount}) { const [count, setCount] = useState(initialCount); return ( <> Count: {count} <button onClick={() => setCount(initialCount)}>Reset</button> <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button> <button onClick={() => setCount(prevCount => prevCount 1)}> </button> </> ); }The ” ” and ”-” buttons use the functional form, because the updated value is based on the previous value. But the “Reset” button uses the normal form, because it always sets the count back to the initial value.
In short, if you want to update a state multiple times before a new render you should always use a functional update. In your scenario this means changing:
setCartItems( cartItems.map((x) => x.id === randomItem.id ? { ...exist, qty: exist.qty 1 } : x ) );
Into
setCartItems((cartItems) => ( // <- uses the updated cartItems value
cartItems.map((x) => (
x.id === randomItem.id ? { ...exist, qty: exist.qty 1 } : x
))
));
The same applies for your else scenario.
After changing your onRandom function to use functional updates you can wrap the contents in a for-loop.
const onRandom = () => {
for (let i = 0; i < 3; i) {
// add random item using functional update
}
};
Or alternatively create a function that holds the logic and call it 3 times.
function onRandom() {
addRandom();
addRandom();
addRandom();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/330797.html
標籤:javascript 反应
