Нажатие на похожие значки увеличивает количество похожих компонентов - PullRequest
2 голосов
/ 16 января 2020

При нажатии одного лайка увеличивается количество лайков для обоих отдельных компонентов. Что вызывает увеличение обоих одинаковых чисел и как я могу их кодировать так, чтобы при нажатии на подобное увеличивалось только одно одинаковое число?

Я также включил консоль на рисунке ниже, где Я записал консоль logi c в мой редуктор. Вы можете найти код для редуктора ниже под картиной.

enter image description here

Код редуктора

import { GET_GOALS, GOAL_ERROR, UPDATE_LIKES } from "../actions/types";

const initialState = {
  goals: [],
  goal: null,
  loading: true,
  error: {}
};

export default function(state = initialState, action) {
  const { type, payload } = action;

  switch (type) {
    case GET_GOALS:
      return {
        ...state,
        goals: payload,
        loading: false
      };
    case GOAL_ERROR:
      return {
        ...state,
        error: payload,
        loading: false
      };
    case UPDATE_LIKES:
      return {
        ...state,
        goals: state.goals.map(goal =>
          console.log("goal id", goal._id) === console.log("payload id", payload.goalId) ? { ...goal, likes: payload.likes } : goal
        ), 
        loading: false
      };
    default:
      return state;
  }
}

Код действия

import axios from "axios";
import { GET_GOALS, GOAL_ERROR, UPDATE_LIKES } from "./types";

// Get goals

export const getGoals = () => async dispatch => {
  try {
    const res = await axios.get("/api/goal/goalfeed");

    dispatch({
      type: GET_GOALS,
      payload: res.data
    });
  } catch (error) {
    dispatch({
      type: GOAL_ERROR,
      payload: { msg: error.response }
    });
  }
};

// Add like

export const addLike = goalId => async dispatch => {
  try {
    const res = await axios.put(`/api/goal/like/${goalId}`);

    dispatch({
      type: UPDATE_LIKES,
      payload: { goalId, likes: res.data }
    });
  } catch (error) {
    dispatch({
      type: GOAL_ERROR,
      payload: { msg: error.response }
    });
  }
};

// Remove like

export const removeLike = goalId => async dispatch => {
  try {

    const res = await axios.put(`/api/goal/unlike/${goalId}`);

    dispatch({
      type: UPDATE_LIKES,
      payload: { goalId, likes: res.data }
    });
  } catch (error) {
    dispatch({
      type: GOAL_ERROR,
      payload: { msg: error.response }
    });
  }
};

Код компонента целей

import React, { useEffect } from "react";
import Moment from "react-moment";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { addLike, removeLike } from "../../actions/goal";
import { getGoals } from "../../actions/goal";
import Spinner from "../layout/Spinner";
import Navbar from "../dashboard/Navbar";
import ThumbUpAltIcon from "@material-ui/icons/ThumbUpAlt";
import ThumbDownAltIcon from "@material-ui/icons/ThumbDownAlt";
import ChatIcon from "@material-ui/icons/Chat";
import DeleteIcon from "@material-ui/icons/Delete";
import DoneIcon from "@material-ui/icons/Done";
import {
  Typography,
  Container,
  CssBaseline,
  makeStyles,
  Grid,
  Avatar,
  Paper,
  Button
} from "@material-ui/core";

const useStyles = makeStyles(theme => ({
  paper: {
    height: "auto",
    marginBottom: theme.spacing(3)
  },
  actionButtons: {
    marginTop: "3vh"
  },
  profileHeader: {
    textAlign: "center",
    marginBottom: 20
  },
  avatar: {
    width: theme.spacing(7),
    height: theme.spacing(7)
  }
}));

const Goals = ({
  getGoals,
  auth,
  addLike,
  removeLike,
  goal: { goals, user, loading }
}) => {
  useEffect(() => {
    getGoals();
  }, [getGoals]);

  const classes = useStyles();


  return loading ? (
    <>
      <Navbar />
      <Container component="main" maxWidth="xs">
        <CssBaseline />
        <div className={classes.paper}>
          <Spinner />
        </div>
      </Container>
    </>
  ) : (
    <>
      <CssBaseline />
      <Navbar />
      <main>
        <Container>
          <Typography variant="h2" className={classes.profileHeader}>
            Goals
          </Typography>
          {/* parent grid */}
          <Grid container spacing={4}>
            {goals.map(singleGoal => (
              <Grid
                className={classes.paper}
                key={singleGoal._id}
                spacing={1}
                container
                item
                direction="row"
                alignItems="center"
                component={Paper}
              >
                <Grid
                  item
                  container
                  direction="column"
                  justify="center"
                  alignItems="center"
                  xs={3}
                >
                  <Avatar className={classes.avatar} src={singleGoal.avatar} />
                  <Typography variant="caption">
                    {singleGoal.first_name} {singleGoal.last_name}
                  </Typography>
                  <Typography variant="caption" className={classes.postedOn}>
                    Posted on{" "}
                    <Moment format="MM/DD/YYYY">{singleGoal.date}</Moment>
                  </Typography>
                </Grid>
                <Grid container item direction="column" xs={9}>
                  <Typography variant="body1">{singleGoal.text}</Typography>
                  <Grid item className={classes.actionButtons}>

                    <Button size="small" onClick={e => addLike(singleGoal._id)}>
                      <ThumbUpAltIcon />
                    </Button>

                    <Typography variant="caption">
                      {singleGoal.likes.length}
                    </Typography>
                    <Button
                      size="small"
                      onClick={e => removeLike(singleGoal._id)}
                    >
                      <ThumbDownAltIcon />
                    </Button>


                      <Button href={`/goal/${singleGoal._id}`} size="small">
                        <ChatIcon />
                      </Button>

                    {!auth.loading && singleGoal.user === auth.user._id && (
                      <Button size="small">
                        <DoneIcon />
                      </Button>
                    )}
                    {!auth.loading && singleGoal.user === auth.user._id && (
                      <Button size="small">
                        <DeleteIcon />
                      </Button>
                    )}
                  </Grid>
                </Grid>
              </Grid>
            ))}
          </Grid>
        </Container>
      </main>
    </>
  );
};

Goals.propTypes = {
  getGoals: PropTypes.func.isRequired,
  goal: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  goal: state.goal,
  auth: state.auth
});

export default connect(mapStateToProps, { getGoals, addLike, removeLike })(
  Goals
);

1 Ответ

2 голосов
/ 16 января 2020

В вашем условном тесте есть недостаток.

state.goals.map(goal =>
  console.log("goal id", goal._id) === console.log("payload id", payload.goalId) // What is this? it will always evaluate to true
    ? { ...goal, likes: payload.likes }
    : goal
)

console.log('EQUAL?', console.log() === console.log()); // true
console.log('EQUAL?', console.log(3) === console.log(3)); // true
console.log('EQUAL?', console.log(3) === console.log('three')); // true
console.log('EQUAL?', console.log('apple') === console.log({})); // true
console.log('EQUAL?', console.log(42) === console.log(-42)); // true

Функция console.log является пустым возвратом, то есть undefined, поэтому вы сравниваете undefined === undefined, что всегда верно.

console.log(undefined === undefined); // true

Вы распространяете новое значение «лайки» на каждый целевой объект.

Попробуйте взамен:

state.goals.map(
  goal => goal._id === payload.goalId 
    ? { ...goal, likes: payload.likes }
    : goal
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...