Обновление списка параметров в дочернем элементе при обновлении родительского состояния - PullRequest
0 голосов
/ 09 июля 2019

Мой список опций (доменов), основанных на выбранном курсе, обновляется в родительском состоянии, но ребенок не будет обновлять / наследовать реквизиты, отправленные с ним. Ребенок должен получить состояние доменов от родителя и составить из него список опций. Он работает при инициализации, но не будет обновляться после изменения курса в родительском компоненте.

AddQuestion.js

class AddQuestion extends Component {

  constructor(props){
      super(props)

      // initiate all states
      this.state = {
        course: '',
        domains: []
      }

  }
  render() {
    return (
      <MainQuestion formError={this.state.formError} levels={this.state.levels} years={this.state.years} courses={this.state.courses} introductionlist={this.state.introductionlist} subQuestions={this.state.subQuestions} numSubQuestion={this.state.numSubQuestion} handleCourseChange={this.handleCourseChange} postQuestion={this.postQuestion} addSubQuestion={this.addSubQuestion} formHasError={this.state.formHasError} validateForm={this.validateForm}/>
    );
  }

  // handle onchange course input
  handleCourseChange = (e) => {
     this.setState({
       course: e.target.value
     },
     function(e) {
      console.log(this.state.course);
      this.getResponseDomains();
      },
     this.validateForm(e)
   );
  }

  // get domains based on course
  getResponseDomains = () => {

    console.log(this.state.course);
    // fetch data from backend
    axios.get('/api/domain/get?course=' + this.state.course, {
      course: this.state.course
    })
    .then(response => response.data.data)
    .then((json) => {

      json.map(obj => this.setState({domains: Object.values(obj) }));
      this.state.domains = json;

      // map a option input for each fetched domain
      let domainslist = Object.keys(this.state.domains).map(key =>
        <option label={this.state.domains[key].name} value={this.state.domains[key].id} />
      )

      this.setState({
        domains: domainslist
      });

    })
    .catch((error) => {
      console.log(error);
    });
  }

  // Add the input field to a new subquestion
  addSubQuestion = () => {
    this.setState({
      numSubQuestion: this.state.numSubQuestion + 1,
      formHasError: true
    });

    //reset array
    subQuestions = [];

    let errormessages = '';
    let errornum = this.state.numSubQuestion + 1;

    //fill array for amount of subquestions needed
    for (var i = 0; i <= this.state.numSubQuestion; i += 1) {
      subQuestions.push(<SubQuestion key={i} number={i + 1} domain={this.state.domain} course={this.state.course} domains={this.state.domains} subjects={this.state.subjects} />);

    this.setState({
      subQuestions: subQuestions,
      formError: errormessages
    });

  }

MainQuestion.js

// This is the main question (e.d. level, year, course and introduction)
class MainQuestion extends Component {

  constructor(props){
      super(props)

  }
  render() {
    return (
      <div className="addQuestion-wrapper">
        <div className="logo mx-auto">
          <img src="/img/logo-white.png"/>
        </div>
        <section className="addQuestion container">
          <form id="addQuestionForm">
            <p className="text-danger">{ this.props.formError }</p> {/* display errors */}
            <div className="row d-flex prequestion">
              <div className="col-12 mb-3">
                <h2>Nieuwe vraag toevoegen</h2>
              </div>
              <div ref="error3" className="input-group col-12 col-lg-6" id="levels-wrapper">
                <div>
                  <p className="label">Niveau</p>
                  {this.props.levels} {/* display fetched levels */}
                </div>
              </div>
              <div ref="error4" className="input-group col-12 col-lg-6" id="years-wrapper">
                <div>
                  <p className="label">Leerjaar</p>
                  {this.props.years} {/* display fetched years */}
                </div>
              </div>
              <div ref="error5" className="input-group col-12 col-lg-6">
              <p className="label">Vak</p>
                <select onChange={this.props.handleCourseChange} name="course" id="select-courses">
                  <option value="" disabled selected>--Kies een vak</option>
                  {this.props.courses} {/* display fetched courses */}
                </select>
              </div>
              <div ref="error10" className="input-group col-12 col-lg-12">
                {this.props.introductionlist} {/* display created introduction textarea */}
              </div>

              </div>

              { this.props.subQuestions } {/* display amount of subquestions in the array */}

              {/* add subquestion button */}
              <div className="AddSubquestion">
                <button className="btn" onClick={ this.props.addSubQuestion } disabled={this.props.formHasError}>Subvraag toevoegen</button>
              </div>

              {/* post question button */}
              <div className="input-group" id="submit">
                <button className="btn" onClick={ this.props.postQuestion } value="Aanmaken" disabled={this.props.formHasError}>Verzend</button>
              </div>

          </form>
        </section>
      </div>
    );
  }



}

export default AddQuestion;

SubQuestion.js

class SubQuestion extends Component {

  constructor(props){
      super(props)

      // initiate all states
      this.state = {
        course: props.course,
        domains: []
      }

  }

  render() {
    return (
      <div className="row d-flex justify-content-center question mt-5">
        <div className="col-12">
          <h3> Subvraag {this.props.number} </h3> {/* display number of subquestion. Fetched from key of created child component */}
        </div>
        <div ref="error" className="input-group col-12 col-lg-6" id="type-wrapper">
          {this.state.type} {/* display fetched type */}
        </div>
        <div ref="error2" className="input-group col-12 col-lg-6" id="questionings-wrapper">
          <div>
            <p className="label">Vraagstelling</p>
            {this.state.questionings} {/* display fetched questionings */}
          </div>
        </div>
        <div ref="error6" className="input-group col-12 col-lg-12">
          {this.state.question} {/* display created textarea for questiona AND answer */}
        </div>
        <div ref="error7" className="input-group col-12 col-lg-6">
          <p className="label">Domein</p>
          <select id="select-domains" name={`domain-${this.props.number}`} onChange={this.handleDomainChange}>
            <option value="" disabled selected>--Kies een domein</option>
            {this.props.domains} {/* display fetched domains */}
          </select>
        </div>
        <div ref="error8" className="input-group col-12 col-lg-6" id="select-subjects">
          <p className="label">Onderwerp</p>
          <select onChange={this.props.handleSubjectChange} name={`subject-${this.props.number}`}>
            <option value="" disabled selected>--Kies een onderwerp</option>
            {this.state.subjects} {/* display fetched subjects */}
          </select>
        </div>
        <div ref="error9" className="input-group col-12 col-lg-12" id="time-points-rtti">
          <div className="time mr-4">
            {/* display time input */}
            <p className="label">Tijdsduur</p>
            <input type="number" name={`tijdsduur-${this.props.number}`} min="1" placeholder="tijd in minuten" onChange={this.props.handleTimeChange}/>
          </div>
          <div className="points mr-4">
            {/* display points input */}
            <p className="label">Punten</p>
            <input type="number" name={`points-${this.props.number}`} min="1" placeholder="punten" onChange={this.props.handlePointsChange}/>
          </div>
          <div className="rtti">
            {/* display rtti input */}
            <p className="label">RTTI</p>
            <input type="radio" name={`RTTI-${this.props.number}`} id={`R-${this.props.number}`} value="1" onChange={this.props.handleRttiChange}/><label htmlFor={`R-${this.props.number}`}>R</label>
            <input type="radio" name={`RTTI-${this.props.number}`} id={`T1-${this.props.number}`} value="2" onChange={this.props.handleRttiChange}/><label htmlFor={`T1-${this.props.number}`}>T1</label>
            <input type="radio" name={`RTTI-${this.props.number}`} id={`T2-${this.props.number}`} value="3" onChange={this.props.handleRttiChange}/><label htmlFor={`T2-${this.props.number}`}>T2</label>
            <input type="radio" name={`RTTI-${this.props.number}`} id={`I-${this.props.number}`} value="4" onChange={this.props.handleRttiChange}/><label htmlFor={`I-${this.props.number}`}>I</label>
          </div>
        </div>
      </div>

    );
  }

  componentWillReceiveProps(nextProps) {
      this.setState({course: nextProps.course, domains: nextProps.domains });
  }

// handle onchange domain input
  handleDomainChange = (e) => {
     this.setState({
       domain: e.target.value
     },
     this.getResponseSubjects, // change subjects based on selected domain
     this.props.validateForm(e)
    );
  }

  // get subjects based on domain
  getResponseSubjects = () => {

    // fetch data from backend
    axios.get('/api/subject/get?domain=' + this.state.domain, {
      domain: this.state.domain
    })
    .then(response => response.data.data)
    .then((json) => {

      json.map(obj => this.setState({subjects: Object.values(obj) }));
      this.state.subjects = json;

      // map a option input for each fetched subject
      let subjectslist = Object.keys(this.state.subjects).map(key =>
        <option label={this.state.subjects[key].name} value={this.state.subjects[key].id} />
      )

      this.setState({
        subjects: subjectslist
      }
      );

    })
    .catch((error) => {
      console.log(error);
    });
  }

export default SubQuestion;

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

Ответы [ 2 ]

0 голосов
/ 10 июля 2019

Я исправил это, вызвав функцию addSubQuestion для handleCourseChange (). Это заставило подзапросы перерисовать.

0 голосов
/ 09 июля 2019

На первый взгляд вы делаете это:

handleCourseChange = (e) => {
     this.setState({
       course: e.target.value
     },
     function(e) {
      console.log(this.state.course);
      this.getResponseDomains();
      },
     this.validateForm(e)
   );
  }

Если я прав, обратный вызов после setState не знает, что такое this, потому что вы объявляете полную функцию вместофункция стрелки.Обычные функции не наследуют this, по умолчанию они не определены.

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