Redux正在为映射数组内的所有元素设置重复值

时间:2019-04-23 00:33:17

标签: reactjs redux

我遇到了redux的问题,未为发布项目附加正确的值。

TLDR:如何告诉Redux仅获得该特定post.id的点赞次数。

不是将所有帖子的点赞设置为第一条帖子的点赞值,而是将其重新设置。

下面的代码获取每个帖子的点赞次数。

export const getLikeCount = (id) => {
    return (dispatch, getState) => {
        return Axios.get(`/api/posts/likes/count/${id}`)
            .then( (res) => {
                 const data = res.data
                 console.log(data); // logs like counts for all posts
                 dispatch({type: GET_LIKES_COUNT, data})
             })

    }
}

然后在减速器上这样调用它。

note:console.log(action.data)打印出这样的值。这些是每个帖子的点赞次数,例如帖子1包含12个赞,帖子2包含2个赞。

enter image description here

import {  ADD_LIKE, GET_LIKES_COUNTT} from '../actions/';

const initialState = {
    post: [],
    postError: null,
    posts:[],
    isEditing:false,
    isEditingId:null,
    likes:0,
    postId:null
}

export default (state = initialState, action) => {
      .....
      case GET_LIKES_COUNT:
          // console.log(action.data)
           return({
              ...state,
              likes:action.data
           })
     case ADD_LIKE:
        console.log(action.id) // renders post id which is 2
        console.log(state.posts) // logs posts array 
        return {
        ...state,
        posts: state.posts.map(post => {
          if (post.id === action.id) {
            return {
              ...post,
              likes: post.likes + 1
            }
          } else return post
        })
      };

问题在于它为错误的帖子附加了错误的值。当帖子1应该有12个赞,帖子2有2个赞时,所有帖子都包含12个赞。简而言之,它没有为每个帖子项目映射正确的值。

{this.props.likeCount}获得帖子顶赞

(this.props.like)获取帖子ID。

这是类似组件

import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCoffee, faAdjust } from '@fortawesome/free-solid-svg-icons';
import {connect} from 'react-redux';
import {  getLikeCount, postLike} from '../actions/';
class Like extends Component{
    constructor(props){
        super(props);
        this.state = {
            likes: null,
            heart: false
        }
    }

    clickLike = (id) => {
        this.props.postLike(id);
        // toggles between css class
        this.setState({
            heart: !this.state.heart
        })
    }
    render(){
       return(
            <div style={{float:'right', fontSize: '1.5em', color:'tomato'}} >
            <i style={{ marginRight: '140px'}} className={this.state.heart ? 'fa fa-heart':'fa fa-heart-o' }>
                    <span style={{ marginLeft: '6px'}}>
                        <a href="#" onClick={ () => this.clickLike(this.props.like)}>Like</a>       
                    </span>
                    {/* gets the like counts */}
                    {this.props.likeCount}
                </i>
            </div>       
       )
    }
}
const mapStateToProps = (state) => ({
    isEditingId: state.post.isEditingId,
    likeCount:state.post.likes
})
const mapDispatchToProps = (dispatch) => ({
    getLikeCount: (id) => dispatch(getLikeCount(id)),
    postLike: (id) => dispatch( postLike(id))
    // Pass id to the DeletePost functions.
});
export default connect(mapStateToProps, mapDispatchToProps)(Like);

将其传递到PostItem组件中,该组件是PostList组件的子代。

PostItem.js

 .....

  render(){
        const {title, id, userId, removePost, createdAt, post_content, 
        username, editForm, isEditing, editChange, myTitle, postUpdate, 
        likes,  clickLike} = this.props
        return(
            <div>
                  .....
                       <Like like={id} />
                  ........
export default connect(null, mapDispatchToProps)(PostItem);

PostList组件(父组件)

这是调用getLikeCount操作的地方。在getLikes函数中调用

import React, { Component } from 'react';
import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import moment from 'moment';
import {connect} from 'react-redux';
import {DeletePost,  getLikeCount, postLike, UpdatePost,EditChange, DisableButton} from '../actions/';
import PostItem from './PostItem';
const Styles = {
    myPaper: {
        margin: '20px 0px',
        padding: '20px'
    }
}
class PostList extends Component{
    constructor(props){
        super(props);
        this.state ={
            title: '',
        }
    }
    // Return a new function. Otherwise the DeletePost action will be dispatch each
     // time the Component rerenders.
    removePost = (id) => () => {
        this.props.DeletePost(id);
    }
    onChange = (e) => {
        e.preventDefault();
        this.setState({
            title: e.target.value
        })
    }
    formEditing = (id) => ()=> {;
        this.props.EditChange(id);
    }
    getLikes = (id) =>  {
        // console.log(id);
        this.props.getLikeCount(id)
        console.log(this.props.likeCount)
    }
    render(){
        const {posts} = this.props;
        return (
            <div>
                {posts.map((post, i) => (
                    <Paper key={post.id} style={Styles.myPaper}>
                     // getting likes here
                     {this.getLikes(post.id)}
                    {/* {...post} prevents us from writing all of the properties out */}
                        <PostItem
                             myTitle={this.state.title} 
                             editChange={this.onChange} 
                             editForm={this.formEditing} 
                             isEditing={this.props.isEditingId === post.id} 
                             removePost={this.removePost} 
                             {...post} 
                        />
                    </Paper>
                ))}
            </div>
        )
    }
}
const mapStateToProps = (state) => ({
    isEditingId: state.post.isEditingId,
})
const mapDispatchToProps = (dispatch) => ({
    // pass creds which can be called anything, but i just call it credentials but it should be called something more 
    // specific.
    EditChange: (id) => dispatch(EditChange(id)),
    UpdatePost: (creds) => dispatch(UpdatePost(creds)),
    getLikeCount: (id) => dispatch(getLikeCount(id)),
    postLike: (id) => dispatch( postLike(id)),
    // Pass id to the DeletePost functions.
    DeletePost: (id) => dispatch(DeletePost(id))
});
export default connect(mapStateToProps, mapDispatchToProps)(PostList);

1 个答案:

答案 0 :(得分:0)

您应该更新您的数据结构。除了在外部设置喜欢计数之外,它还应该是您处于redux状态的帖子的一部分。您的操作还应同时包括帖子ID和顶计数。

export const getLikeCount = (id) => {
    return (dispatch, getState) => {
        return Axios.get(`/api/posts/likes/count/${id}`)
            .then( (res) => {
                 const data = res.data
                 console.log(data); // logs like counts for all posts
                 dispatch({type: GET_LIKES_COUNT, {...data, id}})
             })

    }
}