如何使 React 组件可编辑?
How do I make a React component editable?
在我学习 React 和 firebase 的项目的最后阶段,我遇到了一个问题。通过阅读这两个文档,我了解了大部分的操作方法和操作。
我想从博客 post 中获取内容,然后对其进行编辑,然后使用
post 返回
update()
firebase 有方法。截至目前,我面临的两个错误是我无法编辑该内容,因为反应说它是一个受控元素,我从文档中了解到这是因为我将其作为值传入。
但是,当我尝试删除它并改为在 onInputChange 中创建一个 setState 时,就像文档建议的那样,它得到了更新,但内容空白,输入字段中也缺少原始文本。这意味着我做错了什么反应,但我不确定它是什么。
constructor(props){
super(props);
this.state = {
title: '',
body: '',
post:{},
};
this.onInputChange = this.onInputChange.bind(this);
this.onHandleUpdate = this.onHandleUpdate.bind(this);
}
componentDidMount(){
database.ref(`posts/${this.props.match.params.postId}`)
.on('value', snapshot => {
this.setState({post: snapshot.val()});
});
this.postId= this.props.match.params.postId;
}
onInputChange(e){
this.setState({
title: ‘’, body:''
});
}
onHandleUpdate(e){
console.log(this.postId);
e.preventDefault();
database.ref('posts').child(`${this.postId}`).update(this.state);
this.setState({
title: '',
body: ''
});
}
render() {
return (
<div className="container">
<form onSubmit={this.onHandleUpdate}>
<div className="form-group">
<input value={this.state.title && this.state.post.title} className="form-control" type="text" name="title" ref="title" onChange={this.onInputChange}/>
</div>
<br/>
<div className="form-group">
<input value={this.state.body && this.state.post.body} className="form-control" type="text" name="body" ref="body" onChange={this.onInputChange} />
<br/>
</div>
<button className="btn btn-success">Submit</button>
</form>
</div>
);
}
}
这是目前代码的设置方式。
问题的总结归结为为什么我无法更改文本框中的值。请问我做错了什么?
由于它们是两个单独的字段值,您需要在两个单独的函数中处理它们。你不能用同样的方法onInputChange
。您可以按以下方式更改您的代码。
constructor(props){
super(props);
this.state = {
post:{
title: props.post.title || '',
body: props.post.body|| '',
},
};
this.onTitleChange = this.onTitleChange .bind(this);
this.onBodyChange = this.onBodyChange .bind(this);
this.onHandleUpdate = this.onHandleUpdate.bind(this);
}
componentDidMount(){
database.ref(`posts/${this.props.match.params.postId}`)
.on('value', snapshot => {
this.setState({post: snapshot.val()});
});
this.postId= this.props.match.params.postId;
}
onTitleChange(e){
this.setState({
post: { ...this.state.post,
title: e.target.value}
});
}
onBodyChange(e){
this.setState({
post: { ...this.state.post,
body: e.target.value}
});
}
onHandleUpdate(e){
console.log(this.postId);
e.preventDefault();
database.ref('posts').child(`${this.postId}`).update(this.state);
this.setState({
title: '',
body: ''
});
}
render() {
return (
<div className="container">
<form onSubmit={this.onHandleUpdate}>
<div className="form-group">
<input value={this.state.post.title} className="form-control" type="text" name="title" ref="title" onChange={this.onTitleChange}/>
</div>
<br/>
<div className="form-group">
<input value={this.state.post.body} className="form-control" type="text" name="body" ref="body" onChange={this.onBodyChange} />
<br/>
</div>
<button className="btn btn-success">Submit</button>
</form>
</div>
);
}
或者如果状态是从 componentDidMount 设置的,你的构造函数可能是这样的
constructor(props){
super(props);
this.state = {
post: null, //hope you post contains title and body {title: 'sometitle', body: 'somebody'}
};
如果您想在 React 中创建可编辑的受控输入,请创建具有值的输入以及更改该值的方法:
<input
type="text"
value={this.state.title}
onChange={e => this.handleInputChange(e)}
/>
在上面的代码中,您定义了一对 onChange 处理程序,但您没有将事件传递给它们,因此它们永远没有任何数据可以使用。
对于我的示例,我的 onChange 处理程序可以是:
handleInputChange(e) {
this.setState({
title: e.target.value
});
}
每当我输入我的输入时,它都会改变组件的状态,这将改变我在输入中看到的内容。这有点间接,但这就是受控组件在反应中的工作方式。
如果您添加一个新的输入,那么您可以创建一个新的 onChange 处理程序,一切都应该正常工作。不过,这种方法很快就会变得复杂。创建一个包含 10 个输入的表单,突然间您的组件中有一大堆函数需要处理。
一种更易于管理的方法是创建一个适用于每个输入组件的 onChange 处理程序。您可以通过将要更新的状态字段的名称传递到函数中来创建它。
handleChange(e, field) {
this.setState({
[field]: e.target.value
});
}
然后在你的输入中你可以像这样使用它:
<input
type="text"
value={this.state.title}
onChange={e => this.handleChange(e, "title")}
/>
字段参数是您希望输入更新的字段名称的字符串。
这意味着您可以像这样对正文输入重复使用相同的方法:
type="text"
value={this.state.body}
onChange={e => this.handleChange(e, "body")}
/>
您可以删除onTitleChange 和onBodyChange 方法,并替换为上面的handleChange 方法。简单多了。活动部件越少,损坏的东西就越少。
当您准备好提交表单时,您可以在 onHandleUpdate 方法中使用所需的状态值,如下所示:
onHandleUpdate(e){
e.preventDefault();
database.ref('posts').child(`${this.postId}`).update({
title: this.state.title,
body: this.state.body
});
this.setState({
title: '',
body: ''
});
}
没有必要用 state 中的 post 值来完成整个嵌套操作。您可以随心所欲地嵌套,但在您仍在学习的同时,通过尽可能多地保持非嵌套状态,让事情易于推理。
database.ref(`posts/${this.props.match.params.postId}`)
.on('value', snap => this.setState({
title: snap.val().title,
body: snap.val().body
}));
我制作了一个小沙箱来证明所有这些都有效。 Have a look at the hello component here。我稍微简化了它,我不得不替换数据库调用(因为我没有你的 firebase 密钥),但它应该是有意义的。
你可以用同样的方法处理变化
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
在我学习 React 和 firebase 的项目的最后阶段,我遇到了一个问题。通过阅读这两个文档,我了解了大部分的操作方法和操作。
我想从博客 post 中获取内容,然后对其进行编辑,然后使用
post 返回update()
firebase 有方法。截至目前,我面临的两个错误是我无法编辑该内容,因为反应说它是一个受控元素,我从文档中了解到这是因为我将其作为值传入。
但是,当我尝试删除它并改为在 onInputChange 中创建一个 setState 时,就像文档建议的那样,它得到了更新,但内容空白,输入字段中也缺少原始文本。这意味着我做错了什么反应,但我不确定它是什么。
constructor(props){
super(props);
this.state = {
title: '',
body: '',
post:{},
};
this.onInputChange = this.onInputChange.bind(this);
this.onHandleUpdate = this.onHandleUpdate.bind(this);
}
componentDidMount(){
database.ref(`posts/${this.props.match.params.postId}`)
.on('value', snapshot => {
this.setState({post: snapshot.val()});
});
this.postId= this.props.match.params.postId;
}
onInputChange(e){
this.setState({
title: ‘’, body:''
});
}
onHandleUpdate(e){
console.log(this.postId);
e.preventDefault();
database.ref('posts').child(`${this.postId}`).update(this.state);
this.setState({
title: '',
body: ''
});
}
render() {
return (
<div className="container">
<form onSubmit={this.onHandleUpdate}>
<div className="form-group">
<input value={this.state.title && this.state.post.title} className="form-control" type="text" name="title" ref="title" onChange={this.onInputChange}/>
</div>
<br/>
<div className="form-group">
<input value={this.state.body && this.state.post.body} className="form-control" type="text" name="body" ref="body" onChange={this.onInputChange} />
<br/>
</div>
<button className="btn btn-success">Submit</button>
</form>
</div>
);
}
}
这是目前代码的设置方式。 问题的总结归结为为什么我无法更改文本框中的值。请问我做错了什么?
由于它们是两个单独的字段值,您需要在两个单独的函数中处理它们。你不能用同样的方法onInputChange
。您可以按以下方式更改您的代码。
constructor(props){
super(props);
this.state = {
post:{
title: props.post.title || '',
body: props.post.body|| '',
},
};
this.onTitleChange = this.onTitleChange .bind(this);
this.onBodyChange = this.onBodyChange .bind(this);
this.onHandleUpdate = this.onHandleUpdate.bind(this);
}
componentDidMount(){
database.ref(`posts/${this.props.match.params.postId}`)
.on('value', snapshot => {
this.setState({post: snapshot.val()});
});
this.postId= this.props.match.params.postId;
}
onTitleChange(e){
this.setState({
post: { ...this.state.post,
title: e.target.value}
});
}
onBodyChange(e){
this.setState({
post: { ...this.state.post,
body: e.target.value}
});
}
onHandleUpdate(e){
console.log(this.postId);
e.preventDefault();
database.ref('posts').child(`${this.postId}`).update(this.state);
this.setState({
title: '',
body: ''
});
}
render() {
return (
<div className="container">
<form onSubmit={this.onHandleUpdate}>
<div className="form-group">
<input value={this.state.post.title} className="form-control" type="text" name="title" ref="title" onChange={this.onTitleChange}/>
</div>
<br/>
<div className="form-group">
<input value={this.state.post.body} className="form-control" type="text" name="body" ref="body" onChange={this.onBodyChange} />
<br/>
</div>
<button className="btn btn-success">Submit</button>
</form>
</div>
);
}
或者如果状态是从 componentDidMount 设置的,你的构造函数可能是这样的
constructor(props){
super(props);
this.state = {
post: null, //hope you post contains title and body {title: 'sometitle', body: 'somebody'}
};
如果您想在 React 中创建可编辑的受控输入,请创建具有值的输入以及更改该值的方法:
<input
type="text"
value={this.state.title}
onChange={e => this.handleInputChange(e)}
/>
在上面的代码中,您定义了一对 onChange 处理程序,但您没有将事件传递给它们,因此它们永远没有任何数据可以使用。
对于我的示例,我的 onChange 处理程序可以是:
handleInputChange(e) {
this.setState({
title: e.target.value
});
}
每当我输入我的输入时,它都会改变组件的状态,这将改变我在输入中看到的内容。这有点间接,但这就是受控组件在反应中的工作方式。
如果您添加一个新的输入,那么您可以创建一个新的 onChange 处理程序,一切都应该正常工作。不过,这种方法很快就会变得复杂。创建一个包含 10 个输入的表单,突然间您的组件中有一大堆函数需要处理。
一种更易于管理的方法是创建一个适用于每个输入组件的 onChange 处理程序。您可以通过将要更新的状态字段的名称传递到函数中来创建它。
handleChange(e, field) {
this.setState({
[field]: e.target.value
});
}
然后在你的输入中你可以像这样使用它:
<input
type="text"
value={this.state.title}
onChange={e => this.handleChange(e, "title")}
/>
字段参数是您希望输入更新的字段名称的字符串。
这意味着您可以像这样对正文输入重复使用相同的方法:
type="text"
value={this.state.body}
onChange={e => this.handleChange(e, "body")}
/>
您可以删除onTitleChange 和onBodyChange 方法,并替换为上面的handleChange 方法。简单多了。活动部件越少,损坏的东西就越少。
当您准备好提交表单时,您可以在 onHandleUpdate 方法中使用所需的状态值,如下所示:
onHandleUpdate(e){
e.preventDefault();
database.ref('posts').child(`${this.postId}`).update({
title: this.state.title,
body: this.state.body
});
this.setState({
title: '',
body: ''
});
}
没有必要用 state 中的 post 值来完成整个嵌套操作。您可以随心所欲地嵌套,但在您仍在学习的同时,通过尽可能多地保持非嵌套状态,让事情易于推理。
database.ref(`posts/${this.props.match.params.postId}`)
.on('value', snap => this.setState({
title: snap.val().title,
body: snap.val().body
}));
我制作了一个小沙箱来证明所有这些都有效。 Have a look at the hello component here。我稍微简化了它,我不得不替换数据库调用(因为我没有你的 firebase 密钥),但它应该是有意义的。
你可以用同样的方法处理变化
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}