在更新

时间:2017-11-08 02:39:47

标签: reactjs

我还在学习ReactJS的状态和生命周期,并遇到了一个场景,我提交的表单应该保存表单值,然后将返回的JSON对象追加到数组的末尾渲染存储原始数组的组件。

使用我当前的设置,我有组件设置和表单提交与返回的JSON对象,但状态包含一个空数组而不是对象传播{...comment},它看起来不像setState正在更新组件,但这可能是由于前面提到的空数组。有人能指出我正确的方向吗?

注释:

import React from 'react';
import fetch from 'node-fetch';

//record Comment - Comment Form Handle POST
class CommentForm extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            value: '',
            comments: []
        };
        this.onChange = this.onChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    postComment(comment, recordId, csrfToken) {
        var body = { comment: comment };
        var route = 'http://localhost:3000/record/' + recordId + '/comment';
        fetch(route, 
            { 
                method: 'POST', 
                body: JSON.stringify(body), 
                headers: { 
                    'X-CSRF-Token': csrfToken,
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                }
            })
            .then(res => {
                return res.json();
            })  
            .then(data => {
                console.log(data);
                let commentsArr = this.state.comments;
                this.setState({comments: commentsArr.concat(data)});
            }) 
            .catch(err => {
                console.log(err);
            });
    }

    onChange(e){
        this.setState({
            value: e.target.value
        });
    }

    handleSubmit(e){
        e.preventDefault();
        this.postComment(this.state.value, this.props.recordId, this.props.csrf);
    }

    render(){
        return (
            <div className="record-comment__form">
                <div className="row">
                        <form action={"/record/" + this.props.recordId + "/comment"} method="post" onSubmit={this.handleSubmit}>
                            <input type="hidden" name="_csrf" value={this.props.csrf}/>
                            <textarea name="comment" className="record-comment__form-text-area" onChange={e => this.setState({ value: e.target.value })} value={this.state.value}></textarea>
                            <button type="submit" className="record-comment__form-button" disabled={!this.state.value}>Comment</button>
                        </form>
                </div>
            </div>
        )
    }
}

//record Comment - Comment
const Comment = props => {
    return (
        <div className="row">
            <div className="col-md-12">
                <h5>{props.user_id}</h5>
                <h4>{props.comment}</h4>
                <h3>{props.synotate_user.fullNameSlug}</h3>
            </div>
        </div>
    )
} 

//record Comment - Container
export default class Comments extends React.Component {
    render() {
        return (
            <div className="record-comment-container">
                <CommentForm recordId={this.props.recordId} csrf={this.props.csrf}/>
                { this.props.record_comments.map((comment, i) => 
                    <Comment {...comment} key={this.props.recordCommentId}/>
                )}
            </div>
        );
    }
}

记录(父组件)(正在设置评论的位置):

//GET /api/test and set to state
class RecordFeedContainer extends React.Component{
    constructor(props, context) {
        super(props, context);
        this.state = this.context.data || window.__INITIAL_STATE__ || {records: []};
    }

    fetchList() {
        fetch('http://localhost:3000/api/test')
            .then(res => {
                return res.json();
            })  
            .then(data => {
                console.log(data);
                this.setState({ records: data.record, user: data.user, csrf: data.csrfToken });
            }) 
            .catch(err => {
                console.log(err);
            });
    }

    componentDidMount() {
        this.fetchList();
    }

    render() {
        return (
            <div className="container">
                <h2>Comments List</h2>
                <RecordFeed {...this.state} />
            </div>
        )
    }
};

//Loop through JSON and create Record and Comment Container Component
const RecordFeed = props => {
    return (
        <div>
        { 
            props.records.map((record, index) => {
                return (
                    <div className="row">
                        <div className="col-md-6 col-md-offset-3 record-card">
                            <RecordCard {...record} key={record.recordIdHash} user={props.user} />
                            <Comments {...record} key={index} recordId={record.recordIdHash} csrf={props.csrf}/> 
                        </div>
                    </div>
                );
            })
        }
        </div>
    )
}

2 个答案:

答案 0 :(得分:2)

您的问题是,在呈现<Comments>时,this.props.record_comments不是您在<CommentForm>组件状态下更新的评论。每个组件都有自己的内部状态。

您需要将状态传递给<Comments>组件。您需要将状态移至顶层或使用状态管理系统,如Redux,这将允许您访问可能包含注释数组的共享状态。

从顶级组件中,您可以管理其中的状态,如下所示:

this.state = {
comments: [],
// other shared state
};

您可以将更新注释函数(例如updateCommentsFunc()命名)传递给<CommentForm>,如下所示:

<CommentForm updateComments={this.updateCommentsFunc} recordId={this.props.recordId} csrf={this.props.csrf}/>

这将允许您通过以下内容将更新的注释传递回父组件:

const updateCommentsFunc = (newComments) => {
    this.setState({comments: [...this.state.comments, newComments]});
}

答案 1 :(得分:0)

您的postComment()功能似乎未正确绑定到您的<CommentForm/>组件的this。结果是;从函数中调用this.setState()并没有真正做任何事情。

尝试在构造函数方法中绑定它。

constructor(props) {
  // ...
  this.postComment = this.postComment.bind(this)
}

或者使用As shown in this Image.声明它。

postComment = (comment, recordId, csrfToken) => {
  // ...
}

有关React绑定模式的详细信息,请参阅arrow function