ReactJS:更新受控输入字段问题

时间:2019-07-17 08:08:53

标签: javascript reactjs input

我一直在阅读有关SO的一些主题,但是我不知道如何解决此问题或原因。有人可以像我五岁那样解释它吗?

  

警告:组件正在将文本类型的受控输入更改为   不受控制。输入元素不应从受控切换为   不受控制(反之亦然)。决定使用受控还是   组件生命周期中不受控制的输入元素

我正在开发课程创建者,并且用户必须能够打开现有课程,因此必须以编程方式填充现有课程的内容。

我的构造函数:

  constructor(props) {

    super(props);

    this.state = {
                  lessonID: -1,
                  sectionsArray: [],
                  title: 'No title',
                  type: 'r',
                  language: 'gb',
                  book: 'booka',
                  level: '1',

                  loading: false,

                  saved: true,

                  messageBox: '',

                  lessonOpenModal: false,

    }

    this._state = this.state;

    this.updateSectionsFromChild = this.updateSectionsFromChild.bind(this);

    this.sectionAdd = this.sectionAdd.bind(this);
    this.sectionRemove = this.sectionRemove.bind(this);

    this.menuInput = this.menuInput.bind(this);
    this.menuDropDown = this.menuDropDown.bind(this);

    this.lessonCreate = this.lessonCreate.bind(this);
    this.lessonSave = this.lessonSave.bind(this);
    this.lessonDelete = this.lessonDelete.bind(this);
    this.lessonOpen = this.lessonOpen.bind(this);

    this.sections = [];

    }

这是更新受控组件的功能:

  menuDropDown(event, data) {
    this.setState({
      [data.name]: data.value,
      saved: false,
    });

    console.log(data.name);
    console.log(data.value);
  }

  menuInput(event) {
    this.setState({
      [event.target.name]: event.target.value,
      saved: false,
    });
}

然后这是检索课程并尝试更新状态的代码部分:

  async openLesson(lessonID) {
    await ARLessonOpen(lessonID).then((result) => {

      this.setState(this._state);

      this.setState({
        id: result.lesson.id,
        language: result.lesson.language,
        book: result.lesson.book, // this is a drop down, and it's not causing errors
        type: result.lesson.type, // this is a drop down, and it's not causing errors
        level: result.lesson.level, // this is a drop down, and it's not causing errors
        title: result.lesson.title, // this is an input, and it's not causing errors

        sectionsArray: result.sections.map((section, i) => ({
          key: i,
          id: i,
          title: section.title,
          duration: section.duration,
          content: section.content,
        }))
      })

    }).catch(function(error) {
      console.log(error);
    });
  }

唯一不起作用的字段是“标题”,我不明白为什么。如何以编程方式更新输入值?

JSX:

  renderSections = () => {

    if (this.state.sectionsArray.length > 0) {
      return this.state.sectionsArray.map((section, i) =>
        <LessonSection
          key={section.id}
          id={section.id}
          title={section.title}
          duration={section.duration}
          content={section.content}
          sectionRemove={this.sectionRemove}
          sectionAdd={this.sectionAdd}
          updateSectionsFromChild={this.updateSectionsFromChild}
        />
      )
    } else {
      return (
        <div style={{color: 'black'}}> 
          <Button
            size='mini'
            icon='plus square outline'
            onClick={this.sectionAdd} />
          Add a section to start creating your lesson.
        </div>
      )
    }
  }

  render() {

    return (
      <div className='Lesson-editor'>

        {this.state.messageBox}

        <div style={{display: 'none'}}>

          <DefaultLoader
            active={this.state.loading}
            message={this.state.message}
          />

        </div>

        <div className="Lesson-editor-menu Small-font">

          <div className="Menu-buttons">

            <Button
              size='mini'
              icon='plus square outline'
              onClick={this.sectionAdd} />

            <Button
              size='mini'
              icon='file outline'
              onClick={this.lessonCreate} />

            <DialoglessonOpen
              open={this.state.lessonOpenModal}
              actionOnLessonSelected={(lessonID) => this.openLesson(lessonID)}

              onCancel={() => this.setState({lessonOpenModal: false})} />

            <Button size='mini' icon='open folder outline' text='Open lesson' description='ctrl + o' onClick={this.lessonOpen} />

            <Button
              size='mini'
              icon='save outline'
              onClick={this.lessonSave} />

            <Button
              size='mini'
              icon='delete'
              onClick={this.lessonDelete} />

            <Button
              size='mini'
              icon='delete'
              color='red'
              onClick={ARClearTables} />

          </div>

          <Input
            className='title'
            fluid
            placeholder='Lesson title'
            value={this.state.title}
            name='title'
            onChange={this.menuInput}
          />

          <div>

            <Dropdown
              fluid
              compact
              placeholder='Language'
              search
              selection
              options={lessonLanguages}
              //defaultValue='gb'
              value={this.state.language}
              name='language'
              onChange={this.menuDropDown}
            />

            <Dropdown
              fluid
              compact
              placeholder='Book'
              search
              selection
              options={lessonBooks}
              //defaultValue='booka'
              value={this.state.book}
              name='book'
              onChange={this.menuDropDown}
            />

            <Dropdown
              fluid
              compact
              placeholder='Lesson type'
              search
              selection
              options={lessonTypes}
              defaultValue='r'
              name='type'
              onChange={this.menuDropDown}
            />

            <Dropdown
              fluid
              compact
              placeholder='Lesson level'
              search
              selection
              options={lessonLevels}
              defaultValue='1'
              name='level'
              onChange={this.menuDropDown}
            />

          </div>

        </div>

        <div className='Sections'>
          { this.renderSections() }
        </div>

      </div>
    );
  }
}

2 个答案:

答案 0 :(得分:2)

如果以后要控制输入表单字段的初始值,则不能为undefined或null。它应该是一个空字符串。如果您提供未定义或为null的内容,则它是不受控制的组件。

在您的代码中,React在输入字段中看不到任何值,因此React认为它是第一次安装时不受控制的组件。稍后,当您向React组件添加值时,警告您在没有提供值(不受控制的组件)之后不能提供值(受控制的组件)

答案 1 :(得分:0)

我发现了:问题是我的代码有错误。我正在为null中的输入字段值分配state值。

 async openLesson(lessonID) {
    await ARLessonOpen(lessonID).then((result) => {

      this.setState(this._state);

      this.setState({

        /* HERE: I try to access result.lesson but it's null! I should
            use result.lesson[0]. So the problem is that I was 
            assigning a null value to the input field resulting in the error */

        id: result.lesson.id,
        language: result.lesson.language,
        book: result.lesson.book,
        type: result.lesson.type,
        level: result.lesson.level, 
        title: result.lesson.title,

        sectionsArray: result.sections.map((section, i) => ({
          key: i,
          id: i,
          title: section.title,
          duration: section.duration,
          content: section.content,
        }))
      })

    }).catch(function(error) {
      console.log(error);
    });
  }