React表单单选按钮selectedOption值错误、price状态不更新问题咨询
问题根因
- React 中
useState返回的状态更新函数是异步批量执行的:调用setSelectedOption后,当前函数作用域内的selectedOption变量不会立即更新,仍为更新前的旧值,所以你直接打印、传值给handlePriceChange拿到的都是上一次的状态,就会出现点medium打印small、price不更新的问题。 - 第三个「big」尺寸的单选框
onChange回调里漏写了handlePriceChange调用,选择大尺寸时完全不会触发价格更新逻辑。
修复方案
方案1:直接使用事件对象里的最新值(快速修复)
不要用当前作用域的旧selectedOption,直接取e.target.value作为最新值传递即可,同时补全big尺寸的价格更新调用:
// 三个单选框的onChange统一修改为如下逻辑 onChange={(e) => { const currentVal = e.target.value; setSelectedOption(currentVal); console.log(currentVal); // 直接用最新取到的值 handlePriceChange(currentVal); // 传最新值更新价格 }}
方案2:优化状态逻辑(更易维护,避免同步问题)
price和size本质都是根据selectedOption派生的计算值,完全不需要单独维护state,直接实时计算即可,删掉多余的状态和更新逻辑,从根源避免不同步问题:
import React from "react"; import pizzaStore from "./stores/PizzaStore"; import { observer } from "mobx-react-lite"; import cartStore from "./stores/CartStore"; function ModalWindowComponent({ activeModal, setActiveModal }: any) { const [selectedOption, setSelectedOption] = React.useState("small"); const setClose = () => { setSelectedOption("small"); setActiveModal(false); }; // 直接派生计算price和size,不需要额外state和更新函数 const fixedSize = pizzaStore.size; const size = selectedOption === "small" ? fixedSize : selectedOption === "medium" ? fixedSize * 1.5 : fixedSize * 2; const price = selectedOption === "small" ? pizzaStore.modalProps.price : selectedOption === "medium" ? pizzaStore.modalProps.price * 1.5 : pizzaStore.modalProps.price * 2; const obj = { modalName: pizzaStore.modalProps.name, modalDesc: pizzaStore.modalProps.description, modalSize: size, modalPrice: price, modalImage: pizzaStore.modalProps.imageUrl, }; return ( <div className={activeModal ? "modal active" : "modal"} onClick={() => { setActiveModal(false); setSelectedOption("small"); }} > <div className="modal-content" onClick={(e) => { e.stopPropagation(); }} > <div className="modal-content-header"> <button onClick={() => setClose()}>Close</button> </div> <img src={pizzaStore.modalProps.imageUrl} className="modal-content-img" /> <p className="modal-content-pizza-name">{pizzaStore.modalProps.name}</p> <p className="modal-content-pizza-desc"> {pizzaStore.modalProps.description} </p> <p className="modal-content-pizza-size">{size}см</p> <p className="modal-content-pizza-weight"> {pizzaStore.setWeight(selectedOption)}грамм </p> <p className="modal-content-pizza-price">{price}Руб.</p> <form className="modal-content-sizes-form" onSubmit={(e: any) => { cartStore.handleSubmitForm(e, obj); }} > <label> <input name="radio-size" value="small" type="radio" onChange={(e) => { setSelectedOption(e.target.value); }} checked={selectedOption === "small"} className="modal-content-sizes-form-option" /> Маленькая </label> <label> <input name="radio-size" value="medium" type="radio" onChange={(e) => { setSelectedOption(e.target.value); }} checked={selectedOption === "medium"} className="modal-content-sizes-form-option" /> Средняя </label> <label> <input name="radio-size" value="big" type="radio" onChange={(e) => { setSelectedOption(e.target.value); }} checked={selectedOption === "big"} className="modal-content-sizes-form-option" /> Большая </label> <button onClick={() => { setClose(); console.log(cartStore.cartItems); }} > Добавить </button> </form> </div> </div> ); } export default observer(ModalWindowComponent);
内容的提问来源于stack exchange,提问作者aspiringdev
相关产品推荐
相关产品推荐

