【问题标题】:REACT JS not re-rendering when cartItem removed from state当 cartItem 从状态中移除时,REACT JS 不会重新渲染
【发布时间】:2021-03-24 16:25:52
【问题描述】:

我遇到了一个问题,即 react 未在状态中呈现更新后的 cartItems。状态更新得很好,但我删除的项目实际上并没有从渲染中删除。

我对 react、redux 和状态管理非常陌生,但我认为状态本身实际上并没有什么问题,而是如何/何时迭代项目以进行渲染。只有当我刷新页面时,它才能准确呈现。

import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { Row, Col, ListGroup, Image, Button } from "react-bootstrap";
import Message from "../components/Message";
import { addToCart, removeFromCart } from "../actions/cartActions";

function Basket({ match, location, history }) {
  const productId = match.params.id;
  const qty = location.search ? Number(location.search.split("?")[1]) : 1;
  const specID = location.search ? Number(location.search.split("?")[2]) : 0;

  const dispatch = useDispatch();
  const cart = useSelector((state) => state.cart);
  const { cartItems } = cart;

  useEffect(() => {
    if (productId) {
      dispatch(addToCart(productId, qty, specID));
    }
  }, [dispatch, productId, qty, specID]);

  const removeFromCartHandler = (cartItem) => {
    dispatch(removeFromCart(cartItem));
  };

  const checkoutHandler = () => {
    history.push("/login?redirect=shipping");
  };

  return (
    <Row>
      <Col md={8}>
        {cartItems.length === 0 ? (
          <Message variant="primary">
            Your cart is empty{" "}
            <Link to="/">
              <strong>Go Back</strong>
            </Link>
          </Message>
        ) : (
          <div>
            <Link to="/">
              <strong>Go Back</strong>
            </Link>
            <ListGroup variant="flush">
              {cartItems.map((item) => (
                <ListGroup.Item key={item.product} className="cart">
                  <Row>
                    {/* <Col xs={4} md={2}>
                    <Image src={item.img} alt={item.name} fluid rounded />
                  </Col> */}
                    <Col xs={4} md={3}>
                      <Link to={`/product/${item.product}`}>{item.name}</Link> (
                      {item.size})
                    </Col>
                    <Col xs={2} md={2}>
                      £{item.price}
                    </Col>
                    <Col xs={6} md={3}>
                      Qty
                    </Col>
                    <Col xs={6} md={1}>
                      <Button
                        type="button"
                        variant="light"
                        onClick={() => removeFromCartHandler(item)}
                      >
                        <i className="fas fa-trash" />
                      </Button>
                    </Col>
                  </Row>
                </ListGroup.Item>
              ))}
            </ListGroup>
          </div>
        )}
      </Col>
    </Row>
  );
}

export default Basket;

购物车的减速器。

import { CART_ADD_ITEM, CART_REMOVE_ITEM } from "../constants/cartConstants";

export const cartReducer = (
  state = { cartItems: [{ specList: [{ price: [] }] }] },
  action
) => {
  switch (action.type) {
    case CART_ADD_ITEM:
      const item = action.payload;
      const existItem = state.cartItems.find(
        (x) => x.product === item.product && x.size === item.size
      );

      if (existItem) {
        return {
          ...state,
          cartItems: state.cartItems.map((x) =>
            x.product === existItem.product ? item : x
          ),
        };
      } else {
        return { ...state, cartItems: [...state.cartItems, item] };
      }

    case CART_REMOVE_ITEM:
      return {
        ...state,
        cartItems: state.cartItems.filter((x) => x !== action.payload),
      };
    default:
      return state;
  }
};
import axios from "axios";
import { CART_ADD_ITEM, CART_REMOVE_ITEM } from "../constants/cartConstants";

export const addToCart = (id, qty) => async (dispatch, getState) => {
  const { data } = await axios.get(`/api/products/${id}`);

  dispatch({
    type: CART_ADD_ITEM,
    payload: {
      product: data._id,
      name: data.name,
      image: data.image,
      price: data.price,
      countInStock: data.countInStock,
      qty,
    },
  });

  localStorage.setItem("cartItems", JSON.stringify(getState().cart.cartItems));
};

export const removeFromCart = (id) => async (dispatch, getState) => {
  dispatch({
    type: CART_REMOVE_ITEM,
    payload: id,
  });

  localStorage.setItem("cartItems", JSON.stringify(getState().cart.cartItems));
};

【问题讨论】:

  • 你能把reducer贴出来吗?
  • 您很可能正在改变cartItems 数组。你用splice吗? :)
  • @HMR 我刚刚发布了它。谢谢。
  • @YuryTarabanko 不幸的是,我不知道这将如何实现。我还没用过拼接。
  • @rabin-bhandari NVM 我的猜测是错误的。添加removeFromCart 代码也可能会有所帮助。到目前为止,您发布的代码看起来还不错。

标签: javascript reactjs redux react-redux react-state-management


【解决方案1】:

您正在调用() =&gt; removeFromCartHandler(item),但在其他任何时候假设有效负载为id。你可能想做() =&gt; removeFromCartHandler(item.id)

【讨论】:

  • 就是这样,reducer 也在将有效负载中的对象与数组中的对象进行比较。它也应该是一个id 比较。 state.cartItems.filter((x) =&gt; x.id !== action.payload) 而不是 x !==
猜你喜欢
  • 2020-04-22
  • 2020-01-20
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 2018-11-29
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多