无法从我的购物车中移除(无法在呈现不同组件时更新组件)

Cannot remove from my shopping cart (Cannot update a component while rendering a different component)

我正在制作购物车,但我 运行 出错了,消息准确地说:警告:无法更新组件 (StateProvider) 同时呈现不同的组件(CartDrinks)。在 CartDrinks 中找到错误的 setState() 调用。我正在使用 React Context 来做这件事,但我可以找到解决方案。

这是我的上下文:

import { createContext, useContext, useReducer } from "react";

export const StateContext = createContext();

export const StateProvider = ({ reducer, initialState, children }) => (
    <StateContext.Provider value={useReducer(reducer, initialState)}>
        {children}
    </StateContext.Provider>
)

export const useStateValue = () => useContext(StateContext);

这是我的 Reducer:

export const initialState = {
   cart: [],
}

const reducer = (state, action) => {
   console.log(action)
   switch (action.type) {
       case "ADD_TO_CART":
           return {
               ...state,
               cart: [...state.cart, action.payload]
           };
       case "REMOVE_TO_CART":
           let newCart = [...state.cart];

           const index = state.cart.findIndex((cartItems) => cartItems.id === action.payload.id);
           newCart.splice(index, 1);
           if (index >= 0) {
               newCart.splice(index, 1);
           } else {
               alert('Cant remove drink');
           }
           return { ...state, cart: newCart };
       default:
           return state;
   }
}

export default reducer;

这是我将产品添加到购物车的组件:

import { useStateValue } from '../../context/Context';
import './card.css'

const Card = ({ id, name, image, price }) => {

    const [{ }, dispatch] = useStateValue();

    const addToCard = () => {
        dispatch({
            type: 'ADD_TO_CART',
            item: {
                id: id,
                name: name,
                image: image,
                price: price,
            }
        })
    }

    return (
        <div className="card">
            <img src={image} alt={image} />
            <div className="card__body">
                <h3>{name}</h3>
                <p>Price: $/.{price}</p>
            </div>
            <button onClick={addToCard}>Add to Cart</button>
        </div>
    )
}
export default Card

这是我从购物车中删除产品的组件

import { useStateValue } from "../../context/Context"
import './cart.css'

const CartDrinks = () => {

    const [{ cart }, dispatch] = useStateValue();

    const removeDrink = (id) => {
        dispatch({
            type: "REMOVE_TO_CART",
            id: id
        })
    }

    return (
        <div className="cart__container">
            {cart?.length === 0
                ?
                <p>You don't have nothing</p>
                :
                cart.map((i) => (
                    <div className="cart" key={i.id}>
                        <img src={i.image} alt="" />
                        <div>
                            <h4>{i.name}</h4>
                            <p>$/.{i.price}</p>*
                            <button onClick={removeDrink(i.id)}>remove</button>
                        </div>

                    </div>
                ))
            }

        </div>
    )
}
export default CartDrinks

一切正常,直到我尝试进入我删除产品的组件,进入该组件时出现错误。

挂载 CartDrinks 组件时立即调用 removeDrink 函数。

const removeDrink = (id) => {
  dispatch({
    type: "REMOVE_TO_CART",
    id: id
  })
}

...

<button onClick={removeDrink(i.id)}>remove</button> // <-- immediate call

单击时使用匿名回调调用 removeDrink

<button onClick={() => removeDrink(i.id)}>remove</button>

或将 removeDrink 转换为柯里化函数以关闭 id 和 return 回调。

const removeDrink = (id) => () => {
  dispatch({
    type: "REMOVE_TO_CART",
    id: id
  })
}

...

<button onClick={removeDrink(i.id)}>remove</button>