управление состоянием в реакции с динамически генерируемой формой - PullRequest
1 голос
/ 30 апреля 2020

У меня есть компонент, который получает json список вопросов из API. Затем для каждого вопроса есть 5 переключателей (от «категорически не согласен» до «полностью согласен»).

Вопросы выбираются в componentDidMount (), хранятся в this.state.questions и сопоставляются с questionComponents в рендере (). Компоненты (и переключатели) идентифицируются по ключу.

Мне нужно хранить ответы в виде массива в состоянии. Очевидно, это должно происходить в handleChange, но я не знаю, как это сделать. Я довольно новичок, чтобы реагировать, поэтому, вероятно, есть более простой способ сделать это, чем то, что я делаю сейчас.

Вот приложение. 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;

И Вопрос. 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

1 Ответ

0 голосов
/ 01 мая 2020

Вот рабочий пример для вас:

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>
  )
}

Ответы хранятся в объекте, а не в массиве, поскольку им легче управлять. Вы также можете использовать массив, но обновить его немного сложнее, так как вам нужно l oop по всем элементам, чтобы найти тот, который вы хотите обновить.
Я не знал, как выглядит ваш объект вопроса, поэтому я импровизировал. Обратите внимание, что атрибут key используется React для идентификации элементов, возвращаемых функцией map. Не используйте его иначе.

Надеюсь, это поможет и удачи!

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