Reputation: 351
dishState
return by useReducer
doesn't change even though initDishState
change. Is it caused by asynchronous process which makes the variable mutated somewhere ?
export default function DishModal({
type,
itemCode,
modalRef,
initDishState,
addedOrderState,
}: DishModalType): JSX.Element {
const { menuInfo } = useContext(MenuContext);
const menuDetailData = menuInfo.menu_detail;
const itemInfo = menuDetailData[itemCode];
const [dishState, DishDispatch] = useReducer(dishReducer, initDishState);
console.log("initDishState", initDishState);
console.log("dishState", dishState);
The code when I call DishModal
is
export default function Cart({ cartState }: CartType): JSX.Element {
const { menuInfo } = useContext(MenuContext);
const menuDetail: IPayload = menuInfo.menu_detail;
const ListOfDish = Object.entries(cartState).map(
([dishKey, dishValue], orderIdx) => {
const dishState: IPayload[] = dishValue.state;
const dishInit: IPayload = dishValue.init;
const [, itemCode] = JSON.parse(dishKey);
const dishInfo = menuDetail[itemCode];
if (!dishInfo) return null; // avoid invalid data caused by backend
return (
<Dish
key={orderIdx}
dishKey={dishKey}
dishInfo={dishInfo}
dishState={dishState}
dishInit={dishInit}
/>
);
}
);
return (
<div id="cart">
<div className="clearfix">
<Link to="/" type="button" className="btn-close"></Link>
</div>
<h1>Cart</h1>
{ListOfDish}
</div>
);
}
function Dish({ dishKey, dishInfo, dishState, dishInit }: DishType) {
const { menuInfo } = useContext(MenuContext);
const cartDispatch = useContext(CartDispatchContext);
const modalRef = useRef<HTMLDivElement>(null);
const menuDetailData: IPayload = menuInfo.menu_detail;
const dishQuantity = dishState.length;
const compactState = summarizeDishState(dishState);
const handleModal = () => {
if (modalRef.current) {
const modalController = Modal.getOrCreateInstance(modalRef.current);
modalController.show();
}
};
const ListOfSelectedOption = Object.entries(compactState).map(
([optionCode, optionQuantity]) => {
const optionInfo = menuDetailData[optionCode];
const optionName = attrLang(optionInfo, "lang");
return <li key={optionCode}>{`${optionName} (${optionQuantity})`}</li>;
}
);
return (
<div className="card mb-3">
<div className="row">
<div className="col">
<img
src={imgFullPath(dishInfo.img)}
className="img-fluid rounded-start"
alt="..."
></img>
</div>
<div className="col d-flex flex-column">
<div className="card-body">
<h5>{attrLang(dishInfo, "lang")}</h5>
<ul>{ListOfSelectedOption}</ul>
</div>
<div className="card-footer dish-price">
<strong>{dishInfo.price}</strong>円(税込み
<strong>{Math.round(dishInfo.price * 1.1) || undefined}</strong>円)
</div>
</div>
<div className="col-2">
<button className="btn btn-primary" onClick={handleModal}>
edit
</button>
<DishQuantitySelector
dishKey={dishKey}
addedState={dishInit}
quantity={dishQuantity}
dispatch={cartDispatch}
/>
</div>
</div>
<DishModal
type={"replace"}
itemCode={dishInfo.poscd}
modalRef={modalRef}
initDishState={dishState}
addedOrderState={dishInit}
/>
</div>
);
}
Upvotes: 0
Views: 418
Reputation: 943214
The current value of a reducer isn't supposed to change when the initial value changes. That is why it is called the initial value.
useReducer
returns a dispatcher (which I've renamed here because convention reserves variables starting with a Capital Letter for constructor functions (and components in React)).
const [dishState, dishDispatch] = useReducer(dishReducer, initDishState);
To change the values in the reducer you need to dispatch an action:
dishDispatch({type: 'change', payload: 'foo'});
If you want to use values from props, then you should probably be using the props directly and not involving a reducer.
Upvotes: 2