React冷門但很好用的知識點

介紹

最近在重讀React官方文檔,盤點一些不常用但有用的知識點。如果有啥說的不好的地方,歡迎指正!

推薦個翻譯的不錯的React文檔

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate()爲React生命週期函數, 在render()之前調用。它使得組件能在發生更改之前從 DOM 中捕獲一些信息(例如,滾動位置)。此生命週期的任何返回值將作爲參數傳遞給 componentDidUpdate()

處理聊天滾動的示例:

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // 我們是否在 list 中添加新的 items ?
    // 捕獲滾動位置以便我們稍後調整滾動位置。
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // 如果我們 snapshot 有值,說明我們剛剛添加了新的 items,
    // 調整滾動位置使得這些新 items 不會將舊的 items 推出視圖。
    //(這裏的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

forceUpdate()

默認情況下,當組件的 stateprops 發生變化時,組件將重新渲染。如果 render() 方法依賴於其他數據,則可以調用 forceUpdate() 強制讓組件重新渲染。

調用 forceUpdate() 將致使組件調用 render() 方法,此操作會跳過該組件的 shouldComponentUpdate()。但其子組件會觸發正常的生命週期方法,包括 shouldComponentUpdate() 方法。如果標記發生變化,React 仍將只更新 DOM。

簡單來說forceUpdate()方法可以強制更新組件,所以不建議使用!

key

key顧名思義爲組件的標識,當key改變時組件會重新註冊!但我們使用最多的還是遍歷!

const todos = [1, 2, 3, 4, 5];
const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

其實用index作爲Key有問題,可以看這篇博客

狀態提升

官方解釋:通常,多個組件需要反映相同的變化數據,這時我們建議將共享狀態提升到最近的共同父組件中去。

簡單來說,就是兩個子組件都使用父組件的一個參數,通過props把改參數傳入子組件,並把改變該參數的方法一併傳入子組件,通過調用該方法改變父組件共用的參數!

舉個例子🌰

現在有ComponentA以及ComponentB,他們各有一個輸入框,當我在其中一個輸入框輸入英文單詞時,在另一個組件展示轉換後的大小寫。

class ComponentA extends React.Component {
  // 當input輸入時,在另一個組件顯示大的大小寫轉換
  handleChange(e) => {
    const { onChangeWordUpper } = this.props;
    onChangeWordUpper(e.target.value);
  };

  render() {
    const { word } = this.props;
    return (
      <h2>ComponentA enter: {word}</h2>
      <input onChange={this.handleChange} />
    );
  }
}
class ComponentB extends React.Component {
  // 當input輸入時,在另一個組件顯示大的大小寫轉換
  handleChange(e) => {
    const { onChangeWordLower } = this.props;
    onChangeWordLower(e.target.value);
  };

  render() {
    const { word } = this.props;
    return (
      <h2>ComponentB enter: {word}</h2>
      <input onChange={this.handleChange} />
    );
  }
}

父組件componentFather

class ComponentFather extends React.Component {
  state = {
    word: '';
  }

  // 轉換爲大寫
  onChangeWordUpper(value) => {
    const word = value.toUpperCase()
    this.setState({ word });
  }
  
  // 轉換爲小寫
  onChangeWordLower(value) => {
    const word = value.toLowerCase()()
    this.setState({ word });
  }

  render() {
    const { word } = this.state;
    const componentAProps = {
      word,
      onChangeWordUpper: this.onChangeWordUpper,
    };
    const componentBProps = {
      word,
      onChangeWordUpper: this.onChangeWordLower,
    };
    return (
      <ComponentA {...componentAProps} />
      <ComponentB {...componentBProps} />
    );
  }
}

未完待續

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章