Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

state return by useReducer doesn't change when init value change

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>
  );
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading