在React中如何更新元素映射数组中元素的状态?

时间:2019-12-09 05:51:47

标签: javascript reactjs react-props

我在下面或沙箱here中有两个数据对象和3个层次结构组件。数据包含一个问题列表,每个问题均在其下方显示有输入框,并允许多个答复。但是,在输入对特定问题的答复后,我不知道如何正确更新正确问题的状态。

index.js

import React from 'react';
import { render } from 'react-dom';
import QA from './qa';
//parent of qa.js

const questions = [
  {id : 1,
  question: "where is the origin of chihuahua?"},
  {id : 2,
  question: "when does the great migration happen in Africa?"}
]

const answers = [
  {
    id : 1,
    id_question : 1,
    answer: "Mexico"
    },
  {
    id : 2,
    id_question : 1,
   answer: "Argentina"
  },
  {
    id : 3,
    id_question : 2,
    answer: "Apr"
    },
  {
    id : 4,
    id_question : 2,
    answer: "May"}
]

export default class App extends React.Component {
  state = {
    q : questions, 
    a : answers
    }

  handleSubmit = (val, index) => {
    alert('index',index)
    this.setState({
      ...this.state,
      a: [...this.state.a, {id_question: index, answer: val}]
    });
  }

  render() {
    console.log(this.state)
    return (
      questions.map((q, index) =>
        <QA 
          key={index} 
          question={q.question}
          onSubmit={this.handleSubmit}
          />
      )  
    )
  }
}


render(<App />, document.getElementById('root'));

qa.js

import React from 'react';
import Answer from './answer';
import  "./style.css"
//parent of answer.js

export default class QA extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: ""
    }
  }
  render() {
    const { question } = this.props
    const { text } = this.state
    return (
      <div class='qa-block'>
        <div>Question: {question}</div>
        <Answer onSubmit={this.props.onSubmit}/>
      </div>
    )
  }
}

和answer.js

import React from 'react';

const styles = {
  backgroundColor: 'lightgray',
};

export default class Answer extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: ""
    }
  }
  render() {
    const { text } = this.state
    return (
      <div style={styles}>
        <h4>Answers</h4>
        <input type="text"
          value={text} 
          onInput={(e) => this.setState({ text: e.target.value })} />
        <button onClick={() => this.props.onSubmit(this.state.text)}>Send to the parent</button>
      </div>
    )
  }
}

一些新手问题:

  1. 在哪里调用索引,以便setState附加到state.answer正确的问题ID并将答案ID递增1?
  2. 我应该将答案嵌套为问题的属性吗?

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您可以简单地将QuestionNo作为道具传递给qa和ans组件,然后像下面这样通过回调进行检索:

在index.js中

render() {
    console.log(this.state)
    return (
      questions.map((q, index) =>
        <QA 
          questionNo={index} 
          question={q.question}
          onSubmit={this.handleSubmit}
          />
      )  
    )
  }

在qa.js中

render() {
    const { question, questionNo } = this.props
    const { text } = this.state
    return (
      <div class='qa-block'>
        <div>Question: {question}</div>
        <Answer questionNo={questionNo} onSubmit={this.props.onSubmit}/>
      </div>
    )
  }

在answer.js

render() {
    const { text } = this.state
    return (
      <div style={styles}>
        <h4>Answers</h4>
        <input type="text"
          value={text} 
          onInput={(e) => this.setState({ text: e.target.value })} />
        <button onClick={() => this.props.onSubmit(this.state.text, this.props.questionNo)}>Send to the parent</button>
      </div>
    )
  }

此后,您将在index.js中获得点击项的索引

答案 1 :(得分:1)

因此,要确定问题,您需要将id_question传递给Submit按钮,因此,如果您有参数,则可以在回调函数上获取它。

一旦获得,就可以在对象的答案数组中进行查找并更新userTyped答案。

  handleSubmit = (val, text) => {
    const typedAnswer = {...this.state.a.find(ans => ans.id_question === val), userTypedAnswer: text};
    this.setState({
      ...this.state,
      a: [...this.state.a, typedAnswer]
    });
  }

代码

index.js

import React from 'react';
import { render } from 'react-dom';
import QA from './qa';
//parent of qa.js

const questions = [
  {id: 1,
  question: "where is the origin of chihuahua?"},
  {id: 2,
  question: "when does the great migration happen in africa?"}
]

const answers = [
  {id_question: 1,
  answer: "Mexico"},
  {id_question: 1,
  answer: "Argentina"},
  {id_question: 2,
  answer: "Apr"},
  {id_question: 2,
  answer: "May"}
]

export default class App extends React.Component {
  state = {
    q : questions, 
    a : answers
    }

  handleSubmit = (val, text) => {
    const typedAnswer = {...this.state.a.find(ans => ans.id_question === val), userTypedAnswer: text};
    this.setState({
      ...this.state,
      a: [...this.state.a, typedAnswer]
    });
  }

  render() {
    return (
      <>{
         questions.map((q, index) =>
        <QA 
          key={index} 
          question={q}
          onSubmit={this.handleSubmit}
          />
      )  

      }
       <p>User Typed Answers and questions after submit</p>
       {
         this.state.a.map(ans => (
           ans.userTypedAnswer && <div>
            <span>{ans.id_question}</span>: <span>{ans.userTypedAnswer}</span>
           </div>
         ))
       }
      </>
    )
  }
}


render(<App />, document.getElementById('root'));

// answer.js

import React from 'react';

const styles = {
  backgroundColor: 'lightgray',
};

export default class Answer extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: ""
    }
  }
  render() {
    const { text } = this.state
    const {onSubmit, qid} = this.props
    return (
      <div style={styles}>
        <h4>Answers</h4>
        <input type="text"
          value={text} 
          onInput={(e) => this.setState({ text: e.target.value })} />
        <button onClick={() => onSubmit(qid, this.state.text)}>Send to the parent</button>
      </div>
    )
  }
}

qa.js

import React from 'react';
import Answer from './answer';
import  "./style.css"
//parent of answer.js

export default class QA extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: ""
    }
  }
  render() {
    const { question: {question, id}, onSubmit } = this.props
    const { text } = this.state
    return (
      <div class='qa-block'>
        <div>Question: {question}</div>
        <Answer onSubmit={onSubmit} qid={id}/>
      </div>
    )
  }
}

Working example