我一直在阅读有关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>
);
}
}
答案 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);
});
}