Sunday, May 19, 2024
 Popular · Latest · Hot · Upcoming
108
rated 0 times [  109] [ 1]  / answers: 1 / hits: 6621  / 5 Years ago, wed, september 25, 2019, 12:00:00

Im trying to update my Redux state in a component using a variable passed up to that component from a child, following a form submital callback. The form submits a users comment, which i want to store in my redux state. I'm unsure how to send this variable into the redux chain so i can use it in my action creator. I want to pass the newComment variable inside handleCommentSubmit into the this.props.getVideoComments() action creator. Here is the code:



CommentSection.js (where i want to update my state)



 //redux stuff
import {connect} from 'react-redux'
import {getVideoComments} from '../actions'

class CommentsSection extends React.Component{

constructor(props){
super(props)
//this.state={comments:[], loading:false}

}

componentDidMount(){
this.props.getVideoComments()

}


handleCommentSubmit = (newComment) =>{
// call action creator to dist action to all reducers and update relevant states
this.props.getVideoComments()
//this.setState({comments: [...this.state.comments, newComment]})
//this.setState({comments: newComments},console.log('The current state is now',this.state.comments));
//comment is object with author and message. Add new comment to old comments
//this.setState({comments:[...this.state.comments,newComment]},console.log(this.state, 'state updated'))

}
//Comments are create in comment form, passed up then sent down through commentList to individual comment rendering inside comment.js
// comment form oncommentsubmit running everytime it renders, not only on submital
render(){
const {comments} = this.props
console.log({comments})
return(
<div>
<span><h4> Comments </h4></span>
<div className=ui grid>


<div className = right floated eight wide column >
<CommentList comments={comments}/>
</div>
<div className=left floated eight wide column>

<CommentForm onCommentSubmit={this.handleCommentSubmit}/>

</div>
</div>
</div>

)

}
}

//redux stuff
//called following state update
const mapStateToProps = (state) => {

return {comments:state.videoComments}
}
export default connect(mapStateToProps,{getVideoComments:getVideoComments})(CommentsSection)


index.js (for action creators)



import React from 'react'

export const getVideoComments= ()=> {

return (dispatch, getState)=> {

const videoComments = getState().videoComments

return ({
type: 'GET_VIDEO_COMMENTS',
payload: videoComments
})
}
}


videoCommentsReducer.js



import React from 'react'

const videoCommentsReducer=function(state= [], action){ // reads in previous state
switch (action.type){
case 'GET_VIDEO_COMMENTS':
return action.payload //reducer will update state to be payload.videoComments. Action only describes what happened
// reducer describes how what happened effects state. Could also use previous state and action to create new data
default:
return state
}
}

export default videoCommentsReducer


index.js (in reducer folder where they are combined)



import React from 'react'
import {combineReducers} from 'redux'
import videoCommentsReducer from './videoCommentsReducer'

export default combineReducers({
videoComments:videoCommentsReducer
})

More From » reactjs

 Answers
2

Thought id post my solution as an answer as it combined parts of both answers, but needed bits of both to fully solve the issue.



By combining parts of both the above answers I was able to fully solve the problem. I removed getState() as both fctmolina and Rodrigo Amaral suggested. I also simplified the action creator to returning a javascript object, rather than a function, and so no longer needed to include a dispatch function, or use redux-thunk. I passed the newComment variable into my action creator, and then combined it with my old state inside the reducer. The solution only required a simply definition of the mapDispatchToProps as a JS object containing the action creator getVideoComments, which made it available as a prop to commentSection, and resulted in the action creator being dispatched when the this.props.getVideoComments() function call was made. Here is the altered code:



CommentSection.js



import React from 'react'
import CommentList from './CommentList'
import CommentForm from './CommentForm'


//redux stuff
import {connect} from 'react-redux'
import {getVideoComments} from '../actions'

class CommentsSection extends React.Component{

constructor(props){
super(props)
//this.state={comments:[], loading:false}

}

componentDidMount(){
console.log(this.props.comments)
}


handleCommentSubmit = (newComment) =>{
// call action creator to dist action to all reducers and update relevant states
this.props.getVideoComments(newComment)

}
//Comments are create in comment form, passed up then sent down through commentList to individual comment rendering inside comment.js
// comment form oncommentsubmit running everytime it renders, not only on submital
render(){
const {comments} = this.props
console.log({comments})
return(
<div>
<span><h4> Comments </h4></span>
<div className=ui grid>


<div className = right floated eight wide column >
<CommentList comments={comments}/>
</div>
<div className=left floated eight wide column>

<CommentForm onCommentSubmit={this.handleCommentSubmit}/>

</div>
</div>
</div>

)

}
}

//redux stuff
//called following state update
const mapStateToProps = (state) => {

return {comments:state.videoComments}
}

export default connect(mapStateToProps,{getVideoComments:getVideoComments})(CommentsSection)


videoCommentsReducer.js



import React from 'react'

const videoCommentsReducer=function(state= [], action){ // reads in previous state
switch (action.type){
case 'GET_VIDEO_COMMENTS':
return [...state, action.payload] //reducer will update state to be payload.videoComments. Action only describes what happened
// reducer describes how what happened effects state. Could also use previous state and action to create new data
default:
return state
}
}

export default videoCommentsReducer


index.js (for action creator)



import React from 'react'

export const getVideoComments = (newComment) => {
return({
type: 'GET_VIDEO_COMMENTS',
payload: newComment
})
};


[#6121] Monday, September 23, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
albert

Total Points: 652
Total Questions: 105
Total Answers: 108

Location: Pitcairn Islands
Member since Fri, Oct 15, 2021
3 Years ago
;