如何使React组件可编辑?

时间:2018-02-11 16:14:41

标签: javascript reactjs firebase edit

在我的学习反应和firebase项目的最后阶段,我遇到了一个问题。通过阅读这两本文档,我已经了解了大部分内容的操作方法和内容。

我想从博客文章中获取内容,然后进行编辑并使用

将其发回
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>
      
    );
  }
    
    
    
}

这就是目前代码的设置方式。  问题摘要简单归结为我无法更改文本框中的值的原因。我做错了什么?

3 个答案:

答案 0 :(得分:3)

如果您想在输入中创建输入可编辑的受控输入,请使用值创建输入并更改该值:

<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")}
        />

field参数是您希望输入更新的状态字段名称的字符串。

这意味着您可以为身体输入重复使用相同的方法,如下所示:

  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: ''    
    });
  }

您无需使用状态中的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密钥),但它应该有意义。

答案 1 :(得分:2)

由于它们是两个单独的字段值,您需要在两个单独的函数中处理它们。您不能使用相同的方法Route::get('account/query/{pass?}', 'UsersController@queryPass'); 。您可以更改以下代码。

onInputChange

或者如果state是从componentDidMount设置的,那么你的构造函数可能就像这样

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>

    );
  }

答案 2 :(得分:0)

您可以使用相同的方法来处理更改

handleChange = (e) => {
    this.setState({
        [e.target.name]: e.target.value
    })
}