调用动作时的无限后期循环 [英] infinite post loop when calling action

查看:50
本文介绍了调用动作时的无限后期循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这不是一个特定的错误,我在调用函数时遇到了一个无限的 post 循环

getLikes = (id) =>{//console.log(id);this.props.getLikeCount(id)console.log(this.props.likeCount)}

视觉上是这样的

这是一个无限循环.我们重构了代码,以便用户可以为帖子添加赞、检索特定帖子的赞数量以及更新赞的状态.

Like.js

import React, { Component } from 'react';从'react-dom' 导入 ReactDOM从'@fortawesome/react-fontawesome'导入{FontAwesomeIcon};从@fortawesome/free-solid-svg-icons"导入 { faCoffee, faAdjust };从'react-redux'导入{connect};import { getLikeCount} from '../actions/';类像扩展组件{构造函数(道具){超级(道具);this.state = {喜欢:空}}getLikes = (id) =>{//console.log(id);this.props.getLikeCount(id)console.log(this.props.likeCount)}使成为(){返回(<div style={{float:'right', fontSize:'1.5em', color:'tomato'}} ><i style={{ marginRight: '140px'}} className="fa fa-heart-o"><span style={{ marginLeft: '6px'}}><a href="#" onClick={this.props.like}>赞 </a>{this.getLikes(this.props.postId)}</span>{/* 获得点赞数 */}{this.props.likeCount}</i>

)}}const mapStateToProps = (状态) =>({isEditingId: state.post.isEditingId,喜欢计数:state.post.likes})const mapDispatchToProps = (调度) =>({getLikeCount: (id) =>调度(getLikeCount(id)),//将 id 传递给 DeletePost 函数.});导出默认连接(mapStateToProps, mapDispatchToProps)(Like);

Actions.js

export const postLike = (id) =>{返回(调度)=>{//console.log(userId);return Axios.post('/api/posts/like', {postId: id}).then( (喜欢) => {调度({类型:ADD_LIKE})//console.log('你喜欢这个', like)}).catch((错误)=>{console.log('好像有错误', err);})}}export const getLikeCount = (id) =>{返回(调度,getState)=>{return Axios.get(`/api/posts/likes/count/${id}`).then( (res) => {常量数据 = res.data控制台日志(数据);//记录数据,我可以看到一个数组调度({类型:GET_LIKES_COUNT,数据})})}}

减速器

import { ADD_LIKE, GET_LIKES_COUNT} from '../actions/';常量初始状态 = {喜欢:0,}导出默认值(状态 = 初始状态,动作)=>{开关(动作.类型){案例 GET_LIKES_COUNT://console.log(action.data)返回({...状态,喜欢:action.data})案例ADD_LIKE:返回({...状态,喜欢:state.likes + 1})默认:返回状态}}

PostList.js

import React, { Component } from 'react';从'@material-ui/core/Paper' 导入纸张;从@material-ui/core/Button"导入按钮;从@material-ui/core/Typography"导入排版;从时刻"导入时刻;从'react-redux'导入{connect};导入 {DeletePost, getLikeCount, postLike, UpdatePost,EditChange, DisableButton} from '../actions/';从 './PostItem' 导入 PostItem;常量样式 = {我的论文:{边距:'20px 0px',填充:'20px'}}类 PostList 扩展组件{构造函数(道具){超级(道具);this.state ={标题: '',}}//返回一个新函数.否则 DeletePost 操作将被分派每个//组件重新渲染的时间.removePost = (id) =>() =>{this.props.DeletePost(id);}onChange = (e) =>{e.preventDefault();this.setState({标题:e.target.value})}clickLike = (id) =>{this.props.postLike(id);}表单编辑 = (id) =>()=>{;this.props.EditChange(id);}使成为(){const {posts} = this.props;返回 (<div>{posts.map((post, i) => (<Paper key={post.id} style={Styles.myPaper}>{/* {...post} 阻止我们写出所有的属性 */}<发布项目clickLike={this.clickLike(post.id)}myTitle={this.state.title}editChange={this.onChange}editForm={this.formEditing}isEditing={this.props.isEditingId === post.id}removePost={this.removePost}{...邮政}/></纸>))}

)}}const mapStateToProps = (状态) =>({isEditingId: state.post.isEditingId,})const mapDispatchToProps = (调度) =>({//传递可以被称为任何东西的凭据,但我只是称它为凭据,但它应该被称为更多的东西//具体的.EditChange: (id) =>调度(EditChange(id)),更新帖子:(信用)=>dispatch(UpdatePost(creds)),getLikeCount: (id) =>调度(getLikeCount(id)),postLike: (id) =>调度(postLike(id)),//将 id 传递给 DeletePost 函数.DeletePost: (id) =>调度(DeletePost(id))});导出默认连接(mapStateToProps,mapDispatchToProps)(PostList);

PostItem.js

import React, { Component } from 'react';从'@material-ui/core/Paper' 导入纸张;从@material-ui/core/Button"导入按钮;从@material-ui/core/Typography"导入排版;从时刻"导入时刻;从'./Editable'导入可编辑;从'react-redux'导入{connect};导入 {UpdatePost, getLikeCount, postLike} from '../actions/';从'./Like'导入喜欢;从 '../Axios' 导入 Axios;常量样式 = {我的论文:{边距:'20px 0px',填充:'20px'},按钮:{marginRight:'30px'}}类 PostItem 扩展组件{构造函数(道具){超级(道具);this.state = {禁用:假,}}onUpdate = (id, title) =>() =>{//我们需要 id 以便 express 知道要更新什么帖子,而标题只是编辑标题.if(this.props.myTitle !== null){const 信用 = {身份证,标题}this.props.UpdatePost(creds);}}使成为(){const {title, id, userId, removePost, createdAt, post_content, username, editForm, isEditing, editChange, myTitle, postUpdate, likes, clickLike} = this.props返回(<div><Typography variant="h6" component="h3">{/* if else teneray 运算符 */}{正在编辑?(<可编辑的 editField={myTitle ?myTitle : 标题} editChange={editChange}/>):(<div>{标题}

)}</排版><排版组件="p">{post_content}<h5>作者:{用户名}<Typography color="textSecondary">{moment(createdAt).calendar()}</Typography><Like like={clickLike} postId={id}/></排版>{!isEditing ?(<Button variant="outlined" type="submit" onClick={editForm(id)}>编辑</按钮>):(//传递 id 和 myTitle,我们记得 myTitle 是更新标题时的新值<div><按钮禁用={myTitle.length <= 3}变体=概述"onClick={this.onUpdate(id, myTitle)}>更新</按钮><按钮变体=概述"style={{marginLeft: '0.7%'}}onClick={editForm(null)}>关闭</按钮>

)}{!isEditing &&(<按钮style={{marginLeft: '0.7%'}}变体=概述"颜色=主要"类型=提交"onClick={removePost(id)}>去掉</按钮>)}

)}}const mapStateToProps = (状态) =>({isEditingId: state.post.isEditingId,})const mapDispatchToProps = (调度) =>({//传递可以被称为任何东西的凭据,但我只是称它为凭据,但它应该被称为更多的东西//具体的.更新帖子:(信用)=>dispatch(UpdatePost(creds)),getLikeCount: (id) =>调度(getLikeCount(id)),postLike: (id) =>调度(postLike(id))//将 id 传递给 DeletePost 函数.});导出默认连接(null,mapDispatchToProps)(PostItem);

Posts.js

import React, { Component } from 'react';从 './PostList' 导入 PostList;从'react-redux'导入{connect};import { withRouter, Redirect} from 'react-router-dom';从 '../actions/' 导入 {GetPosts};常量样式 = {我的论文:{边距:'20px 0px',填充:'20px'},包装器:{填充:'0px 60px'}}类 Posts 扩展组件 {状态 = {帖子:[],加载:真实,isEditing: 假,}异步 componentWillMount(){等待 this.props.GetPosts();this.setState({loading: false })const reduxPosts = this.props.myPosts;const ourPosts = reduxPosts控制台日志(reduxPosts);//显示帖子第 35 行}使成为() {const {loading} = this.state;const { myPosts} = this.props如果(!this.props.isAuthenticated){return (<Redirect to='/signIn'/>);}如果(加载){返回加载中..."}返回 (<div className="App" style={Styles.wrapper}><h1>帖子<PostList posts={myPosts}/>

);}}const mapStateToProps = (状态) =>({isAuthenticated: state.user.isAuthenticated,我的帖子:state.post.posts})const mapDispatchToProps = (dispatch, state) =>({GetPosts: () =>调度(GetPosts())});导出默认 withRouter(connect(mapStateToProps,mapDispatchToProps)(Posts));

API 调用 sequelize express 后端

router.get('/likes/count/:postId', (req, res) => {模型.喜欢.计数({其中:{ postId: req.params.postId }}).then (likes=> res.status(200).json(likes)).catch (e => res.status(404))});

解决方案

为了让这件事更简单,我搬家了

clickLike = (id) =>{this.props.postLike(id);}

在 Like 组件内.然而现在

clickLike = (id) =>() =>{this.props.postLike(id);}

() => () => 防止无限 onClick 方法在未经您同意的情况下触发 :).

import React, { Component } from 'react';从'react-dom' 导入 ReactDOM从'@fortawesome/react-fontawesome'导入{FontAwesomeIcon};从@fortawesome/free-solid-svg-icons"导入 { faCoffee, faAdjust };从'react-redux'导入{connect};import { getLikeCount, postLike} from '../actions/';类像扩展组件{构造函数(道具){超级(道具);this.state = {喜欢:空}}clickLike = (id) =>() =>{this.props.postLike(id);}使成为(){返回(<div style={{float:'right', fontSize:'1.5em', color:'tomato'}} ><i style={{ marginRight: '140px'}} className="fa fa-heart-o"><span style={{ marginLeft: '6px'}}><a href="#" onClick={this.clickLike(this.props.like)}>Like </a></span>{/* 获得点赞数 */}{this.props.likeCount}</i>

)}}const mapStateToProps = (状态) =>({isEditingId: state.post.isEditingId,喜欢计数:state.post.likes})const mapDispatchToProps = (调度) =>({getLikeCount: (id) =>调度(getLikeCount(id)),postLike: (id) =>调度(postLike(id))//将 id 传递给 DeletePost 函数.});导出默认连接(mapStateToProps, mapDispatchToProps)(Like);

this.props.like 将从 PostItem 组件获取帖子 ID.它将在 组件中传递.

import React, { Component } from 'react';从'@material-ui/core/Paper' 导入纸张;从@material-ui/core/Button"导入按钮;从@material-ui/core/Typography"导入排版;从时刻"导入时刻;从'./Editable'导入可编辑;从'react-redux'导入{connect};导入 {UpdatePost, getLikeCount, postLike} from '../actions/';从'./Like'导入喜欢;从 '../Axios' 导入 Axios;常量样式 = {我的论文:{边距:'20px 0px',填充:'20px'},按钮:{marginRight:'30px'}}类 PostItem 扩展组件{构造函数(道具){超级(道具);this.state = {禁用:假,}}onUpdate = (id, title) =>() =>{//我们需要 id 以便 expres 知道要更新什么帖子,而标题只是编辑标题.if(this.props.myTitle !== null){const 信用 = {身份证,标题}this.props.UpdatePost(creds);}}使成为(){const {title, id, userId, removePost, createdAt, post_content, username, editForm, isEditing, editChange, myTitle, postUpdate, likes, clickLike} = this.props返回(<div><Typography variant="h6" component="h3">{/* if else teneray 运算符 */}{正在编辑?(<可编辑的 editField={myTitle ?myTitle : 标题} editChange={editChange}/>):(<div>{标题}

)}</排版><排版组件="p">{post_content}<h5>作者:{用户名}<Typography color="textSecondary">{moment(createdAt).calendar()}</Typography><like like={id}/></排版>{!isEditing ?(<Button variant="outlined" type="submit" onClick={editForm(id)}>编辑</按钮>):(//传递 id 和 myTitle,我们记得 myTitle 是更新标题时的新值<div><按钮禁用={myTitle.length <= 3}变体=概述"onClick={this.onUpdate(id, myTitle)}>更新</按钮><按钮变体=概述"style={{marginLeft: '0.7%'}}onClick={editForm(null)}>关闭</按钮>

)}{!isEditing &&(<按钮style={{marginLeft: '0.7%'}}变体=概述"颜色=主要"类型=提交"onClick={removePost(id)}>去掉</按钮>)}

)}}const mapStateToProps = (状态) =>({isEditingId: state.post.isEditingId,})const mapDispatchToProps = (调度) =>({//传递可以被称为任何东西的凭据,但我只是称它为凭据,但它应该被称为更多的东西//具体的.更新帖子:(信用)=>dispatch(UpdatePost(creds)),getLikeCount: (id) =>调度(getLikeCount(id)),postLike: (id) =>调度(postLike(id))//将 id 传递给 DeletePost 函数.});导出默认连接(null,mapDispatchToProps)(PostItem);

{this.getLikes(post.id)} 将在 PostList 组件中被调用.我真的不明白为什么这在这里比 In The Like Component 更有效.这是一种奇怪的方式,您必须在通过帖子映射时放置组件.总而言之,它们不再是无限的 onClick 方法被调度.这是我遇到的问题.

PostList.js

import React, { Component } from 'react';从'@material-ui/core/Paper' 导入纸张;从@material-ui/core/Button"导入按钮;从@material-ui/core/Typography"导入排版;从时刻"导入时刻;从'react-redux'导入{connect};导入 {DeletePost, getLikeCount, postLike, UpdatePost,EditChange, DisableButton} from '../actions/';从 './PostItem' 导入 PostItem;常量样式 = {我的论文:{边距:'20px 0px',填充:'20px'}}类 PostList 扩展组件{构造函数(道具){超级(道具);this.state ={标题: '',}}//返回一个新函数.否则 DeletePost 操作将被分派每个//组件重新渲染的时间.removePost = (id) =>() =>{this.props.DeletePost(id);}onChange = (e) =>{e.preventDefault();this.setState({标题:e.target.value})}表单编辑 = (id) =>()=>{;this.props.EditChange(id);}getLikes = (id) =>{//console.log(id);this.props.getLikeCount(id)console.log(this.props.likeCount)}使成为(){const {posts} = this.props;返回 (<div>{posts.map((post, i) => (<Paper key={post.id} style={Styles.myPaper}>{this.getLikes(post.id)}{/* {...post} 阻止我们写出所有的属性 */}<发布项目myTitle={this.state.title}editChange={this.onChange}editForm={this.formEditing}isEditing={this.props.isEditingId === post.id}removePost={this.removePost}{...邮政}/></纸>))}

)}}const mapStateToProps = (状态) =>({isEditingId: state.post.isEditingId,})const mapDispatchToProps = (调度) =>({//传递可以被称为任何东西的凭据,但我只是称它为凭据,但它应该被称为更多的东西//具体的.EditChange: (id) =>调度(EditChange(id)),更新帖子:(信用)=>dispatch(UpdatePost(creds)),getLikeCount: (id) =>调度(getLikeCount(id)),postLike: (id) =>调度(postLike(id)),//将 id 传递给 DeletePost 函数.DeletePost: (id) =>调度(DeletePost(id))});导出默认连接(mapStateToProps,mapDispatchToProps)(PostList);

这解决了我的大部分问题.但是,以下代码仍然存在一些问题.

为一个帖子点赞,就会为所有人点赞.所以我正在修复它.

This is not so much of a specific error, I'm getting an infinite post loop when calling the function

getLikes = (id) =>   {
    // console.log(id);
    this.props.getLikeCount(id)
    console.log(this.props.likeCount)
}

visually it looks like this

it's an infinite loop. We refactored the code so that a user can add a like to a post, retrieve the amount of likes for a specific post, and update the state of likes.

Like.js

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} from '../actions/';
class Like extends Component{
    constructor(props){
        super(props);
        this.state = {
            likes: null
        }
    }
    getLikes = (id) =>   {
        // console.log(id);
        this.props.getLikeCount(id)
        console.log(this.props.likeCount)
    }
    render(){
        return(
            <div style={{float:'right', fontSize: '1.5em', color:'tomato'}} >
            <i style={{ marginRight: '140px'}} className="fa fa-heart-o">
                    <span style={{ marginLeft: '6px'}}>
                        <a href="#" onClick={this.props.like}>Like </a>
                        {this.getLikes(this.props.postId)}
                    </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)),
    // Pass id to the DeletePost functions.
});
export default connect(mapStateToProps, mapDispatchToProps)(Like);

Actions.js

export const postLike = (id) => {
    return (dispatch) => {
        // console.log(userId);
        return Axios.post('/api/posts/like', {
            postId: id
        }).then( (like) => {
            dispatch({type: ADD_LIKE})
                // console.log('you have liked this', like)
        }).catch( (err)=> {
                console.log('there seem to be an error', err);
        })

    }
}

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 data and i can see an array 
                 dispatch({type: GET_LIKES_COUNT, data})
             })

    }
}

Reducer

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

const initialState = {

    likes:0,

}

export default (state = initialState, action) => {
    switch (action.type) {

        case GET_LIKES_COUNT:
            // console.log(action.data)
            return({
                ...state,
                likes:action.data
            })

        case ADD_LIKE:
            return({
                ...state,
                likes: state.likes + 1
            })
        default:
            return state
    }
}

PostList.js

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
        })
    }
    clickLike = (id)  => {
        this.props.postLike(id);
    }
    formEditing = (id) => ()=> {;
        this.props.EditChange(id);
    }
    render(){
        const {posts} = this.props;
        return (
            <div>
                {posts.map((post, i) => (
                    <Paper key={post.id} style={Styles.myPaper}>
                    {/* {...post} prevents us from writing all of the properties out */}
                        <PostItem
                            clickLike={this.clickLike(post.id)}
                             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);

PostItem.js

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 Editable from './Editable';
import {connect} from 'react-redux';
import {UpdatePost, getLikeCount, postLike} from '../actions/';
import Like from './Like';
import Axios from '../Axios';
const Styles = {
    myPaper: {
        margin: '20px 0px',
        padding: '20px'
    },
    button:{
        marginRight:'30px'
    }
}
class PostItem extends Component{
    constructor(props){
        super(props);
        this.state = {
            disabled: false,
        }
    }
    onUpdate = (id, title) => () => {
        // we need the id so express knows what post to update, and the title being that only editing the title. 
        if(this.props.myTitle !== null){
            const creds = {
                id, title
            }
            this.props.UpdatePost(creds); 
        }
    }
    render(){
        const {title, id, userId, removePost, createdAt, post_content, username, editForm, isEditing, editChange, myTitle, postUpdate, likes,  clickLike} = this.props
        return(
            <div>
                   <Typography variant="h6" component="h3">
                   {/* if else teneray operator */}
                   {isEditing ? (
                          <Editable editField={myTitle ? myTitle : title} editChange={editChange}/>
                   ): (
                       <div>
                           {title}
                       </div>    
                   )}         
                   </Typography>
                   <Typography component="p">
                       {post_content}
                       <h5>
                           by: {username}</h5>
                       <Typography color="textSecondary">{moment(createdAt).calendar()}</Typography>
                       <Like like={clickLike} postId={id}/>
                   </Typography>
                   {!isEditing ? (
                       <Button variant="outlined" type="submit" onClick={editForm(id)}>
                           Edit
                       </Button>
                   ):(     
                       // pass id, and myTitle which as we remember myTitle is the new value when updating the title
                        <div>
                            <Button 
                                disabled={myTitle.length <= 3}
                                variant="outlined" 
                                onClick={this.onUpdate(id, myTitle)}>
                                Update
                            </Button>
                            <Button 
                                variant="outlined" 
                                style={{marginLeft: '0.7%'}}
                                onClick={editForm(null)}>
                                Close
                            </Button>
                        </div>
                   )}
                   {!isEditing && (
                    <Button
                        style={{marginLeft: '0.7%'}}
                        variant="outlined"
                        color="primary"
                        type="submit"
                        onClick={removePost(id)}>
                        Remove
                    </Button>
                    )}
           </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.
    UpdatePost: (creds) => dispatch(UpdatePost(creds)),
    getLikeCount: (id) => dispatch(getLikeCount(id)),
    postLike: (id) => dispatch( postLike(id))
    // Pass id to the DeletePost functions.
});
export default connect(null, mapDispatchToProps)(PostItem);

Posts.js

import React, { Component } from 'react';
import PostList from './PostList';
import {connect} from 'react-redux';
import { withRouter, Redirect} from 'react-router-dom';
import {GetPosts} from '../actions/';
const Styles = {
    myPaper:{
      margin: '20px 0px',
      padding:'20px'
    }
    , 
    wrapper:{
      padding:'0px 60px'
    }
}
class Posts extends Component {
  state = {
    posts: [],
    loading: true,
    isEditing: false, 
  }
  async componentWillMount(){
    await this.props.GetPosts();
    this.setState({ loading: false })
    const reduxPosts = this.props.myPosts;
    const ourPosts = reduxPosts  
    console.log(reduxPosts); // shows posts line 35
  }

  render() {
    const {loading} = this.state;
    const { myPosts} = this.props
    if (!this.props.isAuthenticated) {
      return (<Redirect to='/signIn' />);
    }
    if(loading){
      return "loading..."
    }
    return (
      <div className="App" style={Styles.wrapper}>
        <h1> Posts </h1>
        <PostList posts={myPosts}/>
      </div>
    );
  }
}
const mapStateToProps = (state) => ({
  isAuthenticated: state.user.isAuthenticated,
  myPosts: state.post.posts
})
const mapDispatchToProps = (dispatch, state) => ({
  GetPosts: () => dispatch( GetPosts())
});
export default withRouter(connect(mapStateToProps,mapDispatchToProps)(Posts));

API call sequelize express back end

router.get('/likes/count/:postId', (req, res) => {
   models.Likes.count ({
      where: { postId: req.params.postId }
    })
      .then (likes=> res.status(200).json(likes))
      .catch (e => res.status(404))
});

解决方案

To make this things more simpler, i moved

clickLike = (id)  => {
    this.props.postLike(id);
}

Within the Like Component. However its now

clickLike = (id) => () =>  {
        this.props.postLike(id);
  }

() => () => prevents the infinite onClick method from firing without your consent :).

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
        }
    }
    clickLike = (id) => () =>  {
        this.props.postLike(id);
    }
    render(){
        return(
            <div style={{float:'right', fontSize: '1.5em', color:'tomato'}} >
            <i style={{ marginRight: '140px'}} className="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);

this.props.like will get the post id from the PostItem Component. It will be passed in the <Like/> Component.

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 Editable from './Editable';
import {connect} from 'react-redux';
import {UpdatePost, getLikeCount, postLike} from '../actions/';
import Like from './Like';
import Axios from '../Axios';
const Styles = {
    myPaper: {
        margin: '20px 0px',
        padding: '20px'
    },
    button:{
        marginRight:'30px'
    }
}
class PostItem extends Component{
    constructor(props){
        super(props);
        this.state = {
            disabled: false,
        }
    }
    onUpdate = (id, title) => () => {
        // we need the id so expres knows what post to update, and the title being that only editing the title. 
        if(this.props.myTitle !== null){
            const creds = {
                id, title
            }
            this.props.UpdatePost(creds); 
        }
    }
    render(){
        const {title, id, userId, removePost, createdAt, post_content, username, editForm, isEditing, editChange, myTitle, postUpdate, likes,  clickLike} = this.props
        return(
            <div>
                   <Typography variant="h6" component="h3">
                   {/* if else teneray operator */}
                   {isEditing ? (
                          <Editable editField={myTitle ? myTitle : title} editChange={editChange}/>
                   ): (
                       <div>
                           {title}
                       </div>    
                   )}         
                   </Typography>
                   <Typography component="p">
                       {post_content}
                       <h5>
                           by: {username}</h5>
                       <Typography color="textSecondary">{moment(createdAt).calendar()}</Typography>
                       <Like like={id}/>
                   </Typography>
                   {!isEditing ? (
                       <Button variant="outlined" type="submit" onClick={editForm(id)}>
                           Edit
                       </Button>
                   ):(     
                       // pass id, and myTitle which as we remember myTitle is the new value when updating the title
                        <div>
                            <Button 
                                disabled={myTitle.length <= 3}
                                variant="outlined" 
                                onClick={this.onUpdate(id, myTitle)}>
                                Update
                            </Button>
                            <Button 
                                variant="outlined" 
                                style={{marginLeft: '0.7%'}}
                                onClick={editForm(null)}>
                                Close
                            </Button>
                        </div>
                   )}
                   {!isEditing && (
                    <Button
                        style={{marginLeft: '0.7%'}}
                        variant="outlined"
                        color="primary"
                        type="submit"
                        onClick={removePost(id)}>
                        Remove
                    </Button>
                    )}
           </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.
    UpdatePost: (creds) => dispatch(UpdatePost(creds)),
    getLikeCount: (id) => dispatch(getLikeCount(id)),
    postLike: (id) => dispatch( postLike(id))
    // Pass id to the DeletePost functions.
});
export default connect(null, mapDispatchToProps)(PostItem);

{this.getLikes(post.id)} will be called in the PostList Component. I don't really understand why this works better here than In The Like Component. It's a wierd way you have to place components when mapping through posts. All in all, their is no more infinite onClick methods being dispatched. Which was the problem i was having.

PostList.js

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}>
                     {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);

This solves most of my issues. However, the following code has some issues still.

Liking a post for one post, will like a post for all. So im fixing it atm.

这篇关于调用动作时的无限后期循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆