
本文介绍了调用动作时的无限后期循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
这不是一个特定的错误,我在调用函数时遇到了一个无限的 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 更新</按钮><按钮变体=概述"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 更新</按钮><按钮变体=概述"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.
这篇关于调用动作时的无限后期循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
08-26 05:46