簡體   English   中英

如何使React組件可編輯?

[英]How do I make a React component editable?

在我的學習反應和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> ); } } 

這就是目前代碼的設置方式。 問題摘要簡單歸結為我無法更改文本框中的值的原因。 我做錯了什么?

如果您想在輸入中創建輸入可編輯的受控輸入,請使用值創建輸入並更改該值:

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

我做了一個小沙箱來證明這一切都有效。 看看這里的hello組件 我已經簡化了一點,我不得不更換數據庫調用(因為我沒有你的firebase密鑰),但它應該有意義。

因為它們是兩個單獨的字段值,您需要在兩個單獨的函數中處理它們。 你不能在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>

    );
  }

或者如果state是從componentDidMount設置的,那么你的構造函數可能是這樣的

constructor(props){
    super(props);
    this.state =  {
      post: null,  //hope you post contains title and body {title: 'sometitle', body: 'somebody'}
  };

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM