亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React中的props改變時更新組件的方法是什么

發布時間:2022-04-19 17:23:21 來源:億速云 閱讀:970 作者:iii 欄目:大數據

本文小編為大家詳細介紹“React中的props改變時更新組件的方法是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“React中的props改變時更新組件的方法是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

何時使用派生狀態

咱們先來看一個比較常見的需求,一個用戶列表,可以新增和編輯用戶,當用戶點擊‘新建'
按鈕用戶可以在輸入框中輸入新的用戶名;當點擊‘編輯'按鈕的時候,輸入框中顯示被編輯的用戶名,用戶可以修改;當用戶點擊‘確定'按鈕的時候用戶列表更新。

class UserInput extends React.Component {

 state = {
  user: this.props.user
 }

 handleChange = (e) => {
  this.setState({
   user: {
    ...this.state.user,
    name: e.target.value
   }
  });
 }

 render() {
  const { onConfirm } = this.props;
  const { user } = this.state;
  return (
   <div>
    <input value={user.name || ''} onChange={this.handleChange} />
    <button onClick={() => { onConfirm(user) }}>確定</button>
   </div>
  );
 }
}

class App extends React.Component {
 state = {
  users: [
   { id: 0, name: 'bruce' },
   { id: 1, name: 'frank' },
   { id: 2, name: 'tony' }
  ],
  targetUser: {}
 }

 onConfirm = (user) => {
  const { users } = this.state;
  const target = users.find(u => u.id === user.id);

  if (target) {
   this.setState({
    users: [
     ...users.slice(0, users.indexOf(target)),
     user,
     ...users.slice(users.indexOf(target) + 1)
    ]
   });
  } else {
   const id = Math.max(...(users.map(u => u.id))) + 1;
   this.setState({
    users: [
     ...users,
     {
      ...user,
      id
     }
    ]
   });
  }
 }

 render() {
  const { users, targetUser } = this.state;
  return (
   <div>
    <UserInput user={targetUser} onConfirm={this.onConfirm} />
    <ul>
     {
      users.map(u => (
       <li key={u.id}>
        {u.name}
        <button onClick={() => { this.setState({ targetUser: u }) }}>編輯</button>
       </li>
      ))
     }
    </ul>
    <button onClick={() => { this.setState({ targetUser: {} }) }}>新建</button>
   </div>
  )
 }
}

ReactDOM.render(<App />, document.getElementById('root'));

運行后,效果如圖:

React中的props改變時更新組件的方法是什么

現在點擊‘編輯'和‘新建'按鈕,輸入框中的文字并不會切換,因為點擊‘編輯'和‘更新'時,雖然UserInput的props改變了但是并沒有觸發state的更新。所以需要實現props改變引發state更新,在UserInput中增加代碼:

 componentWillReceiveProps(nextProps) {
  this.setState({
   user: nextProps.user
  });
 }

或者

 static getDerivedStateFromProps(props, state) {
  return {
   user: props.user
  };
 }

這樣就實現了UserInput每次接收新的props的時候自動更新state。但是這種實現方式是有問題的。

派生狀態導致的問題

首先來明確組件的兩個概念:受控數據(controlled data lives)和不受控數據(uncontrollered data lives)。受控數據指的是組件中通過props傳入的數據,受到父組件的影響;不受控數據指的是完全由組件自己管理的狀態,即內部狀態(internal state)。而派生狀態揉合了兩種數據源,當兩種數據源產生沖突時,問題隨之產生。

問題一

當在修改一個用戶的時候,點擊‘確定'按鈕,輸入框里的文字又變成了修改之前的文字。比如我將‘bruce'修改為‘bruce lee',確定后,輸入框中又變成了‘bruce',這是我們不愿意看到的。

React中的props改變時更新組件的方法是什么

出現這個問題的原因是,點擊確定,App會re-render,App又將之前的user作為props傳遞給了UserInput。我們當然可以在每次點擊確定之后將targetUser重置為一個空對象,但是一旦狀態多了之后,這樣管理起來非常吃力。

問題二

假設頁面加載完成后,會異步請求一些數據然后更新頁面,如果用戶在請求完成頁面刷新之前已經在輸入框中輸入了一些文字,隨著頁面的刷新輸入框中的文字會被清除。

我們可以在App中加入如下代碼模擬一個異步請求:

 componentDidMount() {
  setTimeout(() => {
   this.setState({
    text: 'fake request'
   })
  }, 5000);
 }

導致這個問題的原因在于,當異步請求完成,setStateApp會re-render,而組件的componentWillReceiveProps會在父組件每次render的時候執行,而此時傳入的user是一個空對象,所以UserInput的內容被清空了。而getDerivedStateFromProps調用的更頻繁,會在組件每次render的時候調用,所以也會產生該問題。

為了解決這個問題我們可以在componentWillReceiveProps中判斷新傳入的user和當前的user是否一樣,如果不一樣才設置state:

 componentWillReceiveProps(nextProps) {
  if (nextProps.user.id !== this.props.user.id) {
   this.setState({
    user: nextProps.user
   });
  }
 }

更好的解決方案

派生狀態的數據源的不確定性會導致各種問題,那如果每份數據有且只被一個component管理應該就能避免這些問題了。這種思路有兩種實現,一種是數據完全由父組件管理,一種是數據完全由組件自己管理。下面分別討論:

完全受控組件(fully controlled component)

組件的數據完全來自于父組件,組件自己將不需要管理state。我們新建一個完全受控版的UserInput

class FullyControlledUserInput extends React.Component {
 render() {
  const { user, onConfirm, onChange } = this.props;
  return (
   <div>
    <input value={user.name || ''} onChange={onChange} />
    <button onClick={() => { onConfirm(user) }}>確定</button>
   </div>
  )
 }
}

App中調用FullyControlledUserInput的方法如下:

...
  <FullyControlledUserInput
   user={targetUser}
   onChange={(e) => {
    this.setState({
     targetUser: {
      id: targetUser.id,
      name: e.target.value
     }
    });
   }}
   onConfirm={this.onConfirm}
  />
...

現在FullyControlledUserInput中的所有的數據都來源于父組件,由此解決數據沖突和被篡改的問題。

完全不受控組件(fully uncontrolled component)

組件的數據完全由自己管理,因此componentWillReceiveProps中的代碼都可以移除,但保留傳入props來設置state初始值:

class FullyUncontrolledUserInput extends React.Component {
 state = {
  user: this.props.user
 }

 onChange = (e) => {
  this.setState({
   user: {
    ...this.state.user,
    name: e.target.value
   }
  });
 }

 render() {
  const { user } = this.state;
  const { onConfirm } = this.props;
  return (
   <div>
    <input value={user.name || ''} onChange={this.onChange} />
    <button onClick={() => { onConfirm(user) }}>確定</button>
   </div>
  )
 }
}

當傳入的props發生改變時,我們可以通過傳入一個不一樣的key來重新創建一個component的實例來實現頁面的更新。App中調用FullyUncontrolledUserInput的方法如下::

<FullyUncontrolledUserInput
 user={targetUser}
 onConfirm={this.onConfirm}
 key={targetUser.id}
/>

大部分情況下,這是更好的解決方案。或許有人會覺得這樣性能會受影響,其實性能并不會變慢多少,而且如果組件的更新邏輯過于復雜的話,還不如重新創建一個新的組件來的快。

在父組件中調用子組件的方法設置state

如果某些情況下沒有合適的屬性作為key,那么可以傳入一個隨機數或者自增的數字作為key,或者我們可以在組件中定義一個設置state的方法并通過ref暴露給父組件使用,比如我們可以在UserInput中添加:

 setNewUserState = (newUser) => {
  this.setState({
   user: newUser
  });
 }

在App中通過ref調用這個方法:

  ...
  
  <UserInput user={targetUser} onConfirm={this.onConfirm} ref='userInput' />
   <ul>
   {
    users.map(u => (
     <li key={u.id}>
      {u.name}
      <button onClick={() => {
       this.setState({ targetUser: u });
       this.refs.userInput.setNewUserState(u);
      }}>
       編輯
      </button>
     </li>
    ))
   }
  </ul>
  <button onClick={() => {
   this.setState({ targetUser: {} });
   this.refs.userInput.setNewUserState({});
  }}>
   新建
  </button>
  
  ...

讀到這里,這篇“React中的props改變時更新組件的方法是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

上高县| 隆尧县| 秀山| 全州县| 阿坝县| 长葛市| 驻马店市| 太和县| 霸州市| 平定县| 定日县| 灵山县| 田阳县| 筠连县| 措美县| 郑州市| 天峻县| 固阳县| 安多县| 岱山县| 织金县| 乌鲁木齐县| 安溪县| 镇雄县| 平安县| 平山县| 东宁县| 安阳市| 蒙城县| 肇州县| 辽源市| 融水| 策勒县| 陕西省| 丽江市| 宜宾市| 衡阳县| 凉城县| 若羌县| 南召县| 宜川县|