Estoy tratando de agregar artículos en el carrito de compras. Funciona, pero después de agregar artículos, quiero calcular la cantidad de artículos para mostrar en el carrito de compras. La segunda función (calcular ()) no espera que los elementos se enganchen. Por eso, muestra el conteo correcto después de agregar el segundo elemento.
Debajo del código están mis funciones. Como puede ver, al final de la primera función estoy llamando a la función de cálculo () para que continúe.
const [testArray, setTestArray] = useState([]); const [total, setTotal] = useState(0); const [cartCount, setCartCount] = useState(0); function addToTest(product, quantity = 1) { const ProductExist = testArray.find((item) => item.id === product.id); if (ProductExist) { setTestArray( testArray.map((item) => { if (item.id === product.id) { return { ...ProductExist, quantity: ProductExist.quantity + 1 }; } else { return item; } }) ); } else { product.quantity = 1; setTestArray([...testArray, product]); } calculate(); } function calculate() { let resultCount = 0; testArray.map((item) => { console.log("map func works!"); setCartCount(cartCount + item.quantity); }); }
Aquí está mi proyecto de codesandbox, lo mantuve muy simple para no molestarte.
https://codesandbox.io/s/react-template-forked-u95qt?file=/src/App.js
El posible problema ocurre debido a las funciones de sincronización. Por eso, cuando intento async/await, recibo un error sobre los parámetros, porque la primera función tiene un parámetro.
Este es mi primer intento de async/await:
async function calculate(product) { await addToTest(product); let resultCount = 0; testArray.map((item) => { console.log("map func works!"); setCartCount(cartCount + item.quantity); }); }
Como otra solución, traté de usar useEffect tomando los ganchos setArray de referencia. Sin embargo, en este caso, el número de conteo aumenta exponencialmente como 1,3,9...
useEffect(()=>{ let resultCount = 0; testArray.map((item) => { console.log("map func works!"); setCartCount(cartCount + item.quantity); }); },[testArray])
Me pregunto ¿dónde está el problema? Porque cuando uso el código superior en Angular/Typescript, funciona correctamente. Creo que esto sucede debido a los ganchos de reacción, pero no pude entender el problema.
Su idea de usar un useEffect
es buena, pero en lugar de llamar a setCartCount
en cada iteración, debe sumar todos los recuentos de item.quantity
primero y luego llamar a setCartCount
una vez después de su ciclo.
Nota: no use map()
si va a ignorar la matriz que devuelve, use un bucle for
, for...of
como en el ejemplo a continuación, o forEach()
en su lugar.
useEffect(() => { let resultCount = 0; for (const item of testArray) { resultCount += item.quantity; } setCartCount(resultCount); }, [testArray]);
o con reduce()
(aquí desestructurando y renombrando la propiedad de quantity
de cada item
pasado)
useEffect(() => { const resultCount = testArray.reduce((a, { quantity: q }) => a + q, 0); setCartCount(resultCount); }, [testArray]);
Cada llamada a setCartCount
solo actualizará cartCount
en el siguiente procesamiento, por lo que (efectivamente) solo lo está llamando con el elemento final en la matriz. En su lugar, debe usar reduce
en la matriz para obtener el valor que desea y luego configurarlo.
Consulte https://codesandbox.io/s/react-template-forked-u95qt?file=/src/App.js