Как обновить избыточное состояние, используя переменную реагирования, переданную компоненту от дочернего элемента - PullRequest
3 голосов
/ 26 сентября 2019

Я пытаюсь обновить свое состояние Redux в компоненте, используя переменную, переданную этому компоненту от дочернего элемента, после обратного вызова отправки формы.Форма отправляет комментарий пользователя, который я хочу сохранить в своем состоянии избыточности.Я не уверен, как отправить эту переменную в цепочку излишков, чтобы я мог использовать ее в своем создателе действий.Я хочу передать переменную newComment внутри handleCommentSubmit создателю действия this.props.getVideoComments().Вот код:

CommentSection.js (где я хочу обновить свое состояние)

 //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 (для создателей действий)

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 (в папке редуктора, где они объединены)

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

export default combineReducers({
    videoComments:videoCommentsReducer
})

Ответы [ 3 ]

0 голосов
/ 26 сентября 2019

Используйте mapDispatchToProps в вашем CommentSection.js, и нет необходимости использовать getState в вашем создателе действий.

Action Creator

const getVideoComments = (comments) => ({
   type: 'GET_VIDEO_COMMENTS',
   payload: comments,
});

CommentSection.js

// handleCommentSubmit
handleCommentSubmit = (newComment) => {
   this.props.getVideoComments(newComment); //pass comment to action then access newComment in reducer then add it to your state
}

mapDispatchToProps = (state) => {
   getVideoComments: (newComment) => dispatch(getVideoComments(newComment)),
}

export default connect(mapStateToProps, mapDispatchToProps)(CommentsSection);


Reducer.js

case 'GET_VIDEO_COMMENTS':
   return [...state, action.payload];
0 голосов
/ 26 сентября 2019

Мысль опубликует мое решение в качестве ответа, так как оно объединяет части обоих ответов, но для полного решения проблемы нужны были части обоих.

Объединив части обоих вышеупомянутых ответов, я смог полностью решитьпроблема.Я удалил getState (), как предложил fctmolina и Rodrigo Amaral.Я также упростил создатель действия, чтобы он возвращал объект javascript, а не функцию, и поэтому больше не нужно было включать функцию dispatch или использовать redux-thunk.Я передал переменную newComment своему создателю действия, а затем соединил ее со своим старым состоянием внутри редуктора.Для решения этого вопроса потребовалось лишь простое определение mapDispatchToProps как объекта JS, содержащего создателя действия getVideoComments, что сделало его доступным в качестве опоры для commentSection и привело к отправке создателя действия, когда функция this.props.getVideoComments()звонок был сделан.Вот измененный код:

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 (для создателя действий)

import React from 'react'

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

0 голосов
/ 26 сентября 2019

Судя по вашему файлу создателя действий, вы используете промежуточное программное обеспечение redux-thunk , поэтому обязательно импортируйте эту библиотеку и примените ее в магазине.Этот codesandbox показывает полный пример, основанный на вашем.

При использовании этого thunk всегда используйте отправку, которую он предоставляет, чтобы отправить действие вмагазин.Не возвращайте объект от создателя связанных действий :

export const getVideoComments = () => {
  return (dispatch, getState) => {
    const videoComments = getRandomComments();

    dispatch({
      type: "GET_VIDEO_COMMENTS",
      payload: videoComments
    });
  };
};

Кроме того, здесь нет смысла использовать getState для получения комментариев к видео.Вы просто обновите магазин с тем же состоянием снова и снова.getState полезно, когда вы хотите взаимодействовать с другой частью состояния, которая находится за пределами редуктора, который фиксирует ваш тип действия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...