在循环中的setState - React

时间:2016-09-16 11:44:22

标签: ajax reactjs state ruby-on-rails-5

我正在努力建立一份反应问卷。现在,我将使用文本框接受我的所有答案。然后使用ajax调用将它们发送到我的api。我希望我的params有以下结构,

questionnaire: {
                {question: "question", answer: "answer"},
                {question: "question2", answer: "answer2"},
                {question: "question3", answer: "answer3"}
               }

到目前为止,我的代码非常混乱但不知怎的,我得到了理想的结果。但是,我无法更新答案状态并继续获取Uncaught TypeError: Cannot read property 'setState' of undefined

import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom';
import SubmitButton from '../components/SubmitButton'

export default class QuestionaireContainer extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = { q: this.props.data,
                   questionaire: [],
                 };
  }
  componentDidMount() {
    var q = this.state.q
    var questionaire = this.state.questionaire
    q.map(function(map){
      questionaire.push({"id": map.id,
                         "question": map.question,
                         "answer": '',
                        });
    })
    this.setState({questionaire: questionaire})
  }

  submit(e){
    e.preventDefault();
    var data = {
      questionaires: this.state.questionaire
    }
    $.ajax({
      type: "GET",
      url: "/questionaries/save_questions",
      data: data,
      dataType: 'JSON',
      success: ()=>{
        alert("hello")
      }
    })
  }


  render() {
    var questionNodes = this.state.questionaire.map(function(question){

      var updateTextBox = (e) => {
      console.log(question.answer);
      this.setState({"answer": e.target.value});
      }

      return (
        <li key={question.id}>
          <div className="box-sed">
            <div className="que-set registration question-type">
              <span className="icon-ahead">
                <i aria-hidden="true" className="fa fa-question-circle"></i>
              </span>
              <h2>{question.question}</h2>
              <p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500's, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
            </div>
            <div className="registration question-type">
              <input type="text" placeholder="Type answer" className="input-text" value={question.answer} onChange={updateTextBox} />
            </div>
          </div>
        </li>
      );
    });
    return (
      <div className="question">
        <form onSubmit={this.submit.bind(this)}>
          <ul>
          {questionNodes}
          </ul>
          <SubmitButton/>
        </form>
      </div>
    );
  }
}

此外,params是一个数组而不是哈希。我无法弄清楚如何用我的问题设置初始状态。代码可能非常脏,但我只能做到这一点。

我可能不会让自己非常清楚这么好心地忍受我并发表评论,这样我就可以帮助你更好地理解我想要的东西。任何变化和建议都会很棒。在此先感谢:)

- UPDATE -

我最终接受了丹尼尔的建议,并将文本框放在另一个反应组件中并在父组件中调用它。

此外,我在循环内省略了整个状态,并向前移动了this.props 。我更新了子组件text box's中的QuestionaireComponent状态,并使用QuestionaireContainer在父refs组件中使用了其状态。

以下是让我工作的最终代码:

QuestionaireContainer.jsx

import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom';
import SubmitButton from '../components/SubmitButton'
import QuestionaireComponent from '../components/QuestionaireComponent'

export default class QuestionaireContainer extends React.Component {

  submit(e){
    e.preventDefault();
    var data = {
      questionaires: []
    }
    this.props.data.map(map => {
      data.questionaires.push(this.refs[map.id].state)
    });
    console.log(data);
    console.log("Done");
  }
  render() {
    var questionNodes = this.props.data.map(questions => {
      return (
        <QuestionaireComponent question={questions.question} key={questions.id} id = {questions.id} ref={questions.id}/>
      );
    });
    return (
      <div className="question">
        <form onSubmit={this.submit.bind(this)}>
          <ul>
          {questionNodes}
          </ul>
          <SubmitButton/>
        </form>
      </div>
    );
  }
}

QuestionaireComponent.jsx

import React, {PropTypes} from 'react'    
export default class QuestionaireComponent extends React.Component {
  static propTypes = {
    question: PropTypes.string.isRequired,
  };
  constructor(props) {
    super(props);
    this.state = { answer: '',
                   question: this.props.question,
                   id: this.props.id,
                 };
  }
  updateTextBox = (e) => {
    this.setState({answer: e.target.value})
  }
  render() {
    return (
      <li>
        <div className="box-sed">
          <div className="que-set registration question-type">
            <span className="icon-ahead">
              <i aria-hidden="true" className="fa fa-question-circle"></i>
            </span>
            <h2>{this.state.question}</h2>
            <p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500's, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
          </div>
          <div className="registration question-type">
            <input type="text" placeholder="Type answer" className="input-text" value={this.state.answer} onChange={this.updateTextBox} />
          </div>
        </div>
      </li>
    );
  }
}

希望这有助于任何寻找类似事物的人。

1 个答案:

答案 0 :(得分:1)

改变这个:

var questionNodes = this.state.questionaire.map(function(question){

var questionNodes = this.state.questionaire.map(question => {

因为在你的代码函数(问题)中覆盖了上下文变量this