管理与动态生成的表单反应的状态

managing state in react with dynamically generated form

我有一个组件可以从 api 中获取 json 个问题列表。然后每个问题都有 5 个单选按钮供回答(从 "strongly disagree" 到 "strongly agree")。

问题在 componentDidMount() 中获取,存储在 this.state.questions 中,并映射到 render() 中的 questionComponents。组件(和单选按钮)由键标识。

我需要将答案作为数组存储在状态中。这显然必须在 handleChange 中发生,但我不知道该怎么做。我对反应还很陌生,所以可能有比我现在正在做的更简单的方法来做到这一点。

这是App.js

import React from 'react';
import Question from './Question';

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      questions: [],
      answers: []
    }
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(event) {
    const {name, value, type, checked, key} = event.target
    this.setState(prevState => {
      // 
    }
  }

  componentDidMount() {
    fetch("http://localhost:7777/api/questions")
      .then(response => response.json())
      .then(data =>  {

        this.setState({
          questions: data
        })

      })
  }
  render () {
    const questionComponents = this.state.questions.map(question =>
     <Question key={question.id} question={question.question} handleChange = {this.handleChange} />)

    return (
      <div>
        <h1> Questions!</h1>
        {questionComponents}
      </div>
    )
  }

}
export default App;

和Question.js

import React from "react"

function Question(props) {
  return (
    <div className="question">
      <p>{props.question}</p>
      <label>strongly disagree</label>
      <input
        type="radio"
        name={props.key}
        key={props.key}
        value="1"
        onChange={props.handleChange}>
        </input>
        <label> disagree</label>
        <input
          type="radio"
          name={props.key}
          key={props.key}
          value="2"
          onChange={props.handleChange}>
        </input>

        <label>no opinion</label>
        <input
          type="radio"
          name={props.key}
          key={props.key}
          value="3"
          onChange={props.handleChange}>
        </input>

        <label> agree</label>
          <input
            type="radio"
            name={props.key}
            key={props.key}
            value="4"
            onChange={props.handleChange}>
          </input>

          <label>strongly agree</label>
            <input
              type="radio"
              name={props.key}
              key={props.key}
              value="5"
              onChange={props.handleChange}>
            </input>

    </div>
  )
}

export default Question

这是一个适合您的工作示例:

class App extends React.Component {

  constructor() {
    super()
    this.state = {
      questions: [
        {
          id: '123',
          question: 'What?'
        },
        {
          id: '1234',
          question: 'When?'
        }
      ],
      answers: {}
    }
  }

  handleChange = (event) => { // using an arrow function instead of binding in the constructor
    const { name, value } = event.target;
    // this will add / update a key-value pair depending if it exists or not
    this.setState(state => state.answers[name] = value)
  }

  componentDidMount() {
    // import your data
  }

  render() {
    console.log(this.state.answers)
    const { questions } = this.state;
    return (
      <div>
        <h3>Questions</h3>
        {questions.map(question => {
          return <Question key={question.id} name={question.id} question={question.question} handleChange={e => this.handleChange(e)} />
        })}
      </div>
    );
  }
}

function Question(props) {
  // create a label array to loop over instead of typing all input fields
  const labels = ['strongly disagree', 'disagree', 'no opinion', 'agree', 'strongly agree'] 
  return (
    <div className="question">
      <p>{props.question}</p>
      <div className="inputs">
          {labels.map((label, idx) => {
             return (
               <div key={props.name}>
                  <label key={label}>{label}</label>
                  <input
                    type="radio"
                    name={props.name}
                    value={idx + 1}
                    onChange={event => props.handleChange(event)}
                  />
               </div>
             )
          })}
        </div>
    </div>
  )
}

答案存储在对象而不是数组中,因为它更易于管理。您也可以使用数组,但更新它有点困难,因为您必须遍历所有项目才能找到要更新的项目。
我不知道你的问题对象是什么样的,所以我即兴创作了。 请注意,React 使用 key 属性来标识从 map 函数返回的元素。否则不要使用它。

希望对您有所帮助,祝您好运!