在React / Redux电子商店中实现收藏列表逻辑

时间:2019-10-10 11:43:22

标签: reactjs redux redux-thunk

因此,我正在努力争取在一家电子商务商店中刊登商品。 概念 因此,当用户想要保存列表时,他们只需单击心脏图标,该图标就会从灰色变为黑色,变成该特定项目。

我尝试将心脏图标本身作为一个单独的组件,它与后端的交互非常好,但是当我尝试保存一个列表时,所有列表都会变黑。

保存图标组件

import React from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router";
import { Icon } from "antd";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { fetchSave, fetchSaves, saveListing } from "../../redux/actions/saves";
import authHelper from "../../helpers/auth";
import { toast } from "react-toastify";

class Save extends React.Component {
  componentDidMount() {
    if (authHelper()) {
      const { fetchSave, product } = this.props;

      fetchSave(product);
    } else {
      return null;
    }
  }

  handleSaveListing = () => {
    if (authHelper()) {
      const { saveListing, product } = this.props;

      saveListing(product);
      fetchSave(product);
    } else {
      toast.warn("Please login to save product");
    }
  };

  render() {
    const { saved, save, product } = this.props;
    return (
      <Link className="has-text-right hover-effect" onClick={this.handleSaveListing}>
        <Icon
          type="heart"
          style={{
            fontSize: "25px",
            padding: "5px",
            marginLeft: "55%",
            color: `${saved ? "#000000" : "#ebeaea"}`
          }}
        />
      </Link>
    );
  }
}

Save.propTypes = {
  saved: PropTypes.bool,
  save: PropTypes.object
};

Save.defaultProps = {
  saved: false,
  save: {}
};

const mapStateToProps = state => ({
  saved: state.saves.saved,
  save: state.saves.save
});

export default withRouter(
  connect(
    mapStateToProps,
    { fetchSave, saveListing }
  )(Save)
);

单一列表组件


import React from "react";
import { Divider, Icon } from "antd";
import { Link } from "react-router-dom";
import moment from "moment";
import momentTimeZone from "moment-timezone";
import amountFormatter from "../../../helpers/amountFormatter";
import SaveIcon from "../../containers/Save";

const Product = ({ product, handleAddToCart }) => (
  <section className="column is-full-mobile is-two-thirds-tablet is-half-desktop is-one-quarter-widescreen is-one-quarter-fullhd">
    <div className="card">
      <div className="card-image">
        <figure className="image is-3by2">
          <img src={product.images[0]} alt={product.name} />
        </figure>
      </div>
      <div className="card-content">
        <div className="media-content">
          <Link to={`/products/${product._id}`} className="title is-5">
            {product.name}
          </Link>
        </div>
        <div className="media-content">
          Ksh. {amountFormatter(product.amount)}
        </div>
        <Divider />
        <span className="subtitle is-7">
          {moment(
            momentTimeZone.tz(product.createdAt, "Africa/Nairobi"),
            "YYYYMMDD"
          ).fromNow()}
        </span>
        <SaveIcon product={product._id} />
      </div>
    </div>
  </section>
);

export default Product;

保存Redux动作

import { toast } from "react-toastify";
import axios from "axios";
import { LOADING, FETCH_SAVE, FETCH_SAVES, ERROR, SAVE_LISTING } from "../type";

const API = process.env.REACT_APP_API;

export const fetchSaves = () => async dispatch => {
    dispatch({
        type: LOADING
    })
    axios
        .get(`${API}/saves`)
        .then(res => {
            dispatch({
                type: FETCH_SAVES,
                payload: res.data
            })
        })
        .catch(err => {
            dispatch({
                type: ERROR,
                payload: err.response.data
            })
            toast.error(err.response.data.message)
        })
}

export const fetchSave = productId => async dispatch => {
    axios
        .get(`${API}/save/${productId}`)
        .then(res => {
            dispatch({
                type: FETCH_SAVE,
                payload: res.data
            })
        })
        .catch(err => {
            dispatch({
                type: ERROR,
                payload: err.response.data
            })
        })
}

export const saveListing = product => async dispatch => {
    axios
        .post(`${API}/saves`, { product })
        .then(res => {
            dispatch({
                type: SAVE_LISTING,
                payload: res.data
            })
            toast.success(res.data.message)
        })
        .catch(err => {
            dispatch({
                type: ERROR,
                payload: err.response.data
            })
            toast.error(err.response.data.message)
        })
}

保存减速器

import { LOADING, FETCH_SAVES, FETCH_SAVE, SAVE_LISTING } from "../../actions/type";

let initialState = {
    isLoading: false
}

const saveReducer = (state = initialState, action) => {
    switch(action.type)  {
        case LOADING:
            return {
                ...state,
                isLoading: true
            }
        case FETCH_SAVES:
            return {
                ...state,
                saves: action.payload.saves,
                isLoading: false
            }
        case FETCH_SAVE:
            return {
                ...state,
                saved: action.payload.saved,
                isLoading: false,
                save: action.payload.save
            }
        case SAVE_LISTING:
            return {
                ...state,
                saved: action.payload.saved,
                save: action.payload.save
            }
        default: 
            return{
                ...state
            }
    }
}

export default saveReducer;

我希望当我单击单个列表时,在心脏图标上,只有该列表应该变成黑色

1 个答案:

答案 0 :(得分:0)

好吧,我想您应该拥有的保存标志应该在您的产品数组中,因为那是您要列出的内容,然后将产品对象传递给您的Save组件,然后您将执行类似的操作

    <Icon
      type="heart"
      style={{
        fontSize: "25px",
        padding: "5px",
        marginLeft: "55%",
        color: `${product.saved ? "#000000" : "#ebeaea"}`
      }}
    />

然后,您将对所检查的产品进行颜色更改。 如果您看到了现在发生的情况,那么保存对所有产品都是正确的,因为它没有链接到某些产品

希望有帮助