Реализация предпочтительной логики листинга в интернет-магазине React / Redux - PullRequest
0 голосов
/ 10 октября 2019

Так что я работаю над тем, чтобы добавить объявление в интернет-магазин. Концепция Когда пользователь хочет сохранить листинг, он просто нажимает на значок сердца, и он превращается из серого в черный для этого конкретного элемента.

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

Сохранить значок компонента

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;

Сохранение редукционных действий

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 голосов
/ 10 октября 2019

Хорошо, глядя на ваш, я думаю, что флаг сохранения, который у вас есть, должен быть в вашем массиве продуктов, я полагаю, потому что это то, что вы перечисляете, и затем вы передаете объект продукта в свой компонент Save, тогда вы будете делать что-то вроде

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

тогда у вас будет изменение цвета для продукта, который вы взяли. Если вы видите, что происходит сейчас, сохранение относится ко всем вашим продуктам, поскольку оно не связано с каким-либо продуктом

Надеюсь, это поможет

...