Los clientes están seleccionando artículos de restaurante que tienen opciones como ingredientes. Estoy usando casillas de verificación para permitir que el cliente seleccione qué opciones, y cada casilla de verificación tiene el precio agregado de la opción dentro del atributo de valor HTML.
También hay un componente de cantidad que usa una devolución de llamada para modificar un estado React.
(ejemplo de casillas de verificación y selección de cantidad)
El código que se me ocurrió para manejar todo esto es el siguiente:
const [basePrice, setBasePrice] = useState(0); const [price, setPrice] = useState(0); useEffect(() => { let insert = parseFloat(props.item.price); setBasePrice(insert.toFixed(2)); setPrice(insert.toFixed(2)); setQuant(1); }, [props.item]) useEffect(() => { calcPrice(); }, [quant]) const calcPrice = () => { let checked = document.querySelectorAll('input:checked'); let insert = parseFloat(basePrice); for (let i of checked) { insert += parseFloat(i.value); } insert *= parseFloat(quant); setPrice(insert.toFixed(2)); }calcPrice() también se llama dentro del atributo onchange del div que contiene todas las casillas de verificación. Cada vez que un cliente hace clic en una casilla de verificación, llama a calcPrice() .
el primer useEffect() simplemente restablece el precio de visualización ( setPrice(insert.toFixed(2) ) y se ejecuta cada vez que el usuario selecciona un artículo diferente.
El problema que tengo es que cada vez que el cliente selecciona una opción, aumenta la cantidad y luego cambia a un artículo nuevo, no muestra el precio correcto. Llama al segundo useEffect() antes de dejar marcado = document.querySelectorAll() tiene la posibilidad de ejecutarse y utiliza las casillas marcadas del último elemento.
el precio tiene los $3 del último artículo
Pasé una semana y media completa tratando de combinar la cantidad y las casillas de verificación correctamente y, sabiendo que probablemente soy demasiado estúpido para ver la solución obvia, estoy pidiendo ayuda en esto.
Eventualmente, decidí agregar otra variable de estado "primero" que utilizo para determinar si la cantidad cambió o no debido a que el cliente hizo clic en otro elemento, evitando que se ejecute el segundo useEffect() antes de dejarlo marcado = document.querySelectorAll('input :marcado') tuvo la oportunidad de hacerlo.
No me gusta esta solución en absoluto. Funciona, me alegro, pero se siente pirateado. Aquí está el código:
const ItemModal = (props) => { const [quant, setQuant] = useState(1); const [basePrice, setBasePrice] = useState(0); const [price, setPrice] = useState(0); const [first, setFirst] = useState(false); useEffect(() => { let insert = parseFloat(props.item.price); setBasePrice(insert.toFixed(2)); setPrice(insert.toFixed(2)); setQuant(1); setFirst(true); }, [props.item]) if (!first || quant > 1) { calcPrice(); } if (first) { setFirst(false); } }, [quant]) const calcPrice = () => { let checked = document.querySelectorAll('input:checked'); let insert = parseFloat(basePrice); for (let i of checked) { insert += parseFloat(i.value); } insert *= parseFloat(quant); setPrice(insert.toFixed(2)); }la línea || quant > 1 es necesario en la declaración if dentro del segundo useEffect() porque, de lo contrario, el botón de cantidad no funcionará correctamente cuando se seleccione un nuevo elemento. El cliente debe presionar el botón de cantidad al menos dos veces antes de que comience a funcionar, ya que primero se establece en falso en el primer clic.