处理onChange并设置输入数组的状态

时间:2016-06-17 03:19:37

标签: reactjs

只是一些背景知识,我是javascript和web开发的新手,但在React上做了一些教程很开心。我第一次在stackoverflow上发帖!

我正在构建一个组件来显示是/否问题列表,用户必须通过选择单选按钮并在文本区域中添加一些注释来做出响应。我不确定我应该如何为使用map生成的输入数组设置状态。

我有一个数组抱着我的问题:

var questions = [
    {id:"1", text:"Is the source up to date?"},
    {id:"2", text:"Question 2 placeholder"},
    {id:"3", text:"Question 3 placeholder"},
]

这是我的(未完成的)组件:

var QuestionList = React.createClass({
    getInitialState: function () {
        return {
            commentText: "",
        }
    },

    onUpdateComments: function (e) {
        this.setState({
            commentText: e.target.value
        });
    },
    render: function () {
        var QuestionLines = this.props.questions.map(function(question) {
            return (
                <div key={question.id}>
                    <div>
                        <div>
                            {question.text}
                        </div>
                        <label>
                            <input type="radio" name={question.id} value = {question.id+'Y'}/>Yes
                        </label>
                        <label>
                            <input type="radio" name={question.id} value = {question.id+'N'}/>No
                        </label>
                    </div>
                    <div>
                        <textarea 
                            name = {question.id}
                            onChange = {this.onUpdateComments}
                            placeholder="Enter comments here" 
                            value={this.state.commentText} />
                    </div>
                </div>
            );
        }, this);
        return (
            <div>
                {QuestionLines}
            </div>
        )
    }
});

该应用程序现在在所有3个textareas中显示相同的文本,我可以看到这是因为我将所有更改存储在textarea相同的commmentText状态。但是,我真的很难过我需要做些什么来分离这些并使这项工作。任何帮助都会很感激。

另外,正如我所提到的,我对此非常陌生,所以如果关于我如何构建我的组件有什么不对,请告诉我。

谢谢!

3 个答案:

答案 0 :(得分:0)

只需将commentText设置为对象:

var QuestionList = React.createClass({
    getInitialState: function () {
        return {
            commentText: {},
        }
    },

    onUpdateComments: function (e) {

        // Note that e.target.name is question.id
        var target = e.target;
        this.state.commentText[target.name] = target.value;
        this.forceUpdate();
    },
    render: function () {
        var QuestionLines = this.props.questions.map(function(question) {

            var id = question.id; // store id

            return (
                <div key={id}>
                    <div>
                        <div>
                            {question.text}
                        </div>
                        <label>
                            <input type="radio" name={id} value = {id+'Y'}/>Yes
                        </label>
                        <label>
                            <input type="radio" name={id} value = {id+'N'}/>No
                        </label>
                    </div>
                    <div>
                        <textarea 
                            name = {id}
                            onChange = {this.onUpdateComments}
                            placeholder="Enter comments here" 
                            value={this.state.commentText[id]} />
                    </div>
                </div>
            );
        }, this);
        return (
            <div>
                {QuestionLines}
            </div>
        )
    }
});

查看onUpdateCommentsvalue={this.state.commentText[id]}之间的差异。

注意: 如果您使用babel编译代码,可以像这样编写onUpdateComments

onUpdateComments: function (e) {

    // Note that e.target.name is question.id
    var target = e.target;
    this.setState(function(previousState) {
      return {
        commentText: {
          ...previousState.commentText, 
          [target.name]: target.value
        }
      }
    });
},

答案 1 :(得分:0)

一种解决方案是使用一个commentTextStore对象,其中键(属性)是commentIds,然后您将每个问题文本区域写入对应于commentId的值。

答案 2 :(得分:0)

我会做那样的事情:

var QuestionList = React.createClass({
    getInitialState: function () {
        return { comments: {} } //set internal state comment as an empty object
    },

    onUpdateComments: function (id, e) {

        /*
            you can modify your state only using setState. But be carefull when trying to grab actual state and modify it's reference.
            So, the best way is to create a new object (immutable pattern), and one way of doing that is to use Object.assign
        */
        var comments = Object.assign({}, this.state.comments);

        /* set, for instance, comment[1] to "some text" */
        comments[id] = e.target.value;

        /* set the state to the new variable */
        this.setState({comments: comments});


    },
    render: function () {
        var QuestionLines = this.props.questions.map(function(question) {

            /* grab the comment for this ID. If undefined, set to empty */
            var comment = this.state.comments[question.id] || "";

            return (
                <div key={question.id}>
                    <div>
                        <div>
                            {question.text}
                        </div>
                        <label>
                            <input type="radio" name={question.id} value = {question.id+'Y'}/>Yes
                        </label>
                        <label>
                            <input type="radio" name={question.id} value = {question.id+'N'}/>No
                        </label>
                    </div>
                    <div>
                        <textarea 
                            name = {question.id}
                            onChange = {this.onUpdateComments.bind(this,question.id)}
                            placeholder="Enter comments here" 
                            value={comment} />
                    </div>
                </div>
            );
        }, this);
        return (
            <div>
                {QuestionLines}
            </div>
        )
    }
});