Действие Redux onClick не запускается из компонента, нет ошибок или ошибок консоли - PullRequest
1 голос
/ 05 августа 2020

У меня есть приложение eCommerce React, которое я собираю, для просмотра элементов. Каждый элемент имеет кнопку Добавить в корзину с функцией onClick, которая отправляет действие ADD_ITEM для обновления состояния корзины.

Проблема, которую я вижу, заключается в том, что Действие никогда не запускается, и состояние никогда не обновляется, но нет никаких ошибок консоли или чего-либо, что указывало бы мне в направлении того, что сломано.

Я просматривал все снова и снова, нет опечатки, и все связано с магазином, поэтому я действительно не понимаю, почему он не работает.

Cart Reducer

import { AnyAction } from "redux";
import CartActionTypes from "./cart.types";

const INITIAL_STATE = {
  hidden: true,
  cartItems: [],
};

const cartReducer = (state = INITIAL_STATE, action: AnyAction) => {
  switch (action.type) {
    case CartActionTypes.TOGGLE_CART_HIDDEN:
      return {
        ...state,
        hidden: !state.hidden,
      };
    case CartActionTypes.ADD_ITEM:
      return {
        ...state,
        cartItems: [...state.cartItems, action.payload],
      };
    default:
      return state;
  }
};

export default cartReducer;

Cart Actions

import CartActionTypes from "./cart.types";

export const toggleCartHidden = () => ({
  type: CartActionTypes.TOGGLE_CART_HIDDEN,
});

export const addItem = (item) => ({
  type: CartActionTypes.ADD_ITEM,
  payload: item,
});

Cart Types

const CartActionTypes = {
  TOGGLE_CART_HIDDEN: "TOGGLE_CART_HIDDEN",
  ADD_ITEM: "ADD_ITEM",
};

export default CartActionTypes;

Root Reducer

import { combineReducers } from "redux";

import userReducer from "./user/user.reducer";
import cartReducer from "./cart/cart.reducer";

export default combineReducers({
  user: userReducer,
  cart: cartReducer,
});

Item Component with onClick/mapDispatchToProps function

import React from "react";
import styled from "styled-components";
import { connect } from "react-redux";
import { addItem } from "../../redux/cart/cart.actions";
import { Item } from "../../pages/shop/shop.component";

const CollectionItem = ({ item }: { item: Item }) => {
  const { name, price, imageUrl } = item;

  return (
    <CollectionItemContainer>
      <Image
        style={{ backgroundImage: `url(${imageUrl})` }}
        className="image"
      />
      <CollectionFooter>
        <Name>{name}</Name>
        <Price>{price}</Price>
      </CollectionFooter>
      <CollectionItemButton
        onClick={() => addItem(item)}
        className="custom-button inverted"
      >
        Add to cart
      </CollectionItemButton>
    </CollectionItemContainer>
  );
};

const mapDispatchToProps = (dispatch) => ({
  addItem: (item) => dispatch(addItem(item)),
});

export default connect(null, mapDispatchToProps)(CollectionItem);

Item Collection component (Parent of Item Component)

import React from "react";
import styled from "styled-components";
import { Item } from "../../pages/shop/shop.component";
import CollectionItem from "../collection-item/collection-item.component";

const CollectionPreview = ({
  title,
  items,
}: {
  title: string;
  items: Array<Item>;
}) => {
  return (
    <CollectionPreviewContainer>
      <Title>{title.toUpperCase()}</Title>
      <Preview>
        {items
          .filter((item, idx) => idx < 4)
          .map((item) => (
            <CollectionItem key={item.id} item={item} />
          ))}
      </Preview>
    </CollectionPreviewContainer>
  );
};

export default CollectionPreview;

1 Ответ

2 голосов
/ 05 августа 2020

В вашем коде есть только очень небольшая, но очень важная проблема: в вашем CollectionItem компоненте вы не используете функцию addItem из ваших реквизитов, которая была введена connect с вашей mapDispatchToProps функцией . Вы, вероятно, хотели деструктурировать его в определении функции вашего CollectionItem компонента, но просто забыли об этом.

изменение

const CollectionItem = ({ item }: { item: Item }) =>

на

const CollectionItem = ({ item, addItem }: { item: Item, addItem: () => void }) =>

должно исправить проблема.

Обратите внимание, что вы не увидели никаких ошибок, потому что ваш создатель действий также называется addItem. Поэтому, когда вы вызываете addItem в функции onClick, функция по-прежнему определяется, даже если вы не деструктурировали ее из реквизита. Однако вызов создателя действия вместо функции из mapDispatchToProps просто создаст действие (простой объект js) и вернет его, не отправляя его ...

Чтобы избежать таких трудно обнаруживаемых ошибок, я рекомендовал бы называть функцию, введенную через mapDispatchToProps, иначе, чем создатель действия.

Пример:

const CollectionItem = ({ item /* missing fn here */ }: { item: Item }) => {
  const { name, price, imageUrl } = item;

  return (
    <CollectionItemContainer>
      <Image
        style={{ backgroundImage: `url(${imageUrl})` }}
        className="image"
      />
      <CollectionFooter>
        <Name>{name}</Name>
        <Price>{price}</Price>
      </CollectionFooter>
      <CollectionItemButton
        onClick={() => handleAddItem(item)}
        className="custom-button inverted"
      >
        Add to cart
      </CollectionItemButton>
    </CollectionItemContainer>
  );
};

const mapDispatchToProps = (dispatch) => ({
  handleAddItem: (item) => dispatch(addItem(item)),
});

Нет, ошибка станет очевидной, потому что функция handleAddItem не будет выдана определенная ошибка, и вы сразу узнаете, что вам не хватает функции handleAddItem в первой строке этого примера.

...