Elaine's Blog 朝著 senior 前進的工程師

React 學習筆記

2018-08-21

有無 state

  • 如果有 state
    • 用 component 的方式宣告一個 class
    • 可以 access state
      • 透過 this.state 或 this.props
    • 有生命週期 hook
class XY extend Component{
    ...
}
  • 如果沒有 state
    • 用 function 的方式就好了
const XY = (props) => {
    ...
}

Container 與 Presentational Components

  • Presentational Components
    • 用途:怎麼看事情(Markup、外觀)
    • 是否讓 Redux 意識到:否
    • 取得資料方式:從 props 取得
    • 改變資料方式:從 props 去呼叫 callback function
    • 寫入方式:手動處理
  • Container Components
    • 用途:怎麼做事情(擷取資料,更新 State)
    • 是否讓 Redux 意識到:是
    • 取得資料方式:訂閱 Redux State(store)
    • 改變資料方式:Dispatch Redux Action
    • 寫入方式:從 React Redux 產生

Component 主要負責單純的 UI 的渲染,而 Container 則負責和 Redux 的 store 溝通,作為 Redux 和 Component 之間的橋樑

Container 與 Presentational Components 入門

key

  • 每個元素都有一個唯一的 key,可以來比較哪一個元素需要被更新(它的 DOM)
    • 不建議用 index
      • 如果列表改變,每一個元素都會收到一個新的 index
    • 通常都用 id

不要直接改變陣列和物件(因為這些都是指標)

  • 複製物件
    • 利用 Object.assign() 複製
      const person = Object.assign({}, this.state.person);
      
    • 利用 … 複製
      const person = {
      ...this.state.person
      };
      
  • 複製陣列

    • 利用 splice() 複製
    const persons = this.state.persons.splice();
    
    • 利用 … 複製
    const persons = [...this.state.persons];
    
  • 淺層複製的問題

JSX

  • jsx 要有判斷式的話,裡面只能用三元表示式
// 只能用
{
  showPerson ? <p>I'm a person.</p> : null;
}

// 不能用
{
  if (showPerson) {
    return <p>I'm a person.</p>;
  } else {
    return null;
  }
}

生命週期

Mounting 載入

元件正要被載入到 DOM 階段

  • componentWillMount()

    • 這個方法是在我們元件第一次要 render 到畫面前會執行,整個生命過程只會執行一次
    • 你可能會想說可以在這個地方用 setState 方法將 state 初始化,雖然 setState 方法的確可以在這邊被調用,不過沒人會這樣寫,應該要寫在 constructor 裡面,用 this.state 來對 state 初始化
  • componentDidMount()

    • 大部分 Ajax 要進行處理都是在這個方法裡面調用,不在 componentWillMount() 階段進行 Ajax 主要是因為沒辦法確定對資料的請求能在畫面 render 之前處理好

Updating 更新

當 state 或 props 改變時,會進行 re-render 階段

  • componentWillReceiveProps(nextProps)

    • 當收到新的 props,會觸發此函數
    • 如果需要收到新的 props ,需要改變 state 時,可以調用此函數
    • 在剛開始 init props 階段,並不會觸發此函數
    • this.setState() 也不會觸發此函數
  • shouldComponentUpdate(nextProps, nextState)

    • 在此函數內判斷是否新的值和舊的值不一樣,再決定要不要 re-render
    • 這麼做有個好處就是一旦你有一大堆組件的情況,每次在面對傳入一樣的 props 或 state 都還要 re-render 那就太浪費效能了,所以這個方法能幫你解決這些問題,讓效能變好
      • return true 代表照正常 re-render 方式變更元件
      • return false 代表就不會變更元件
    • 不要做太多深層的檢查或使用 JSON.stringify(),以避免造成效能上的問題
    • PureComponet 已經內建這種檢查,他會檢查所有新舊 state 和 props,如有差異才會繼續更新
// 改變 props
shouldComponentUpdate (nextProps, nextState){
    return nextProps.person != this.state.persons;

// 改變 state
shouldComponentUpdate (nextProps, nextState){
    return nextState.person != this.state.persons;
}
  • componentWillUpdate()

    • 不能在這裡呼叫 this.setState(),會陷入無限迴圈
    • 不能在這裡進行 dispatch Redux action,這樣會導致在 componentWillUpdate 之前觸發另一個更新元件的動作
  • componentDidUpdate()

    • 此函數在初始執行階段不會被觸發
    • 當 shouldComponentUpdate() 返回 false 時,也不會被觸發
  • getSnapshotBeforeUpdate(react16.3)

    • 可以用來記錄滾動位置

Unmounting 移除

元件要從 DOM 移除階段

  • componentWillUnmount()
    • 在元件被刪除”之前”,會立刻執行此函數
    • 可以被用來解除一些時間綁定、中斷 HTTP 請求或者進行 unsubscribe 處理

正確的使用 setState

  • 陣列和物件需要先複製一份,再改變,再更新
  • 如果需要取得之前的值
this.setState({
  count: this.count + 1
});
  • 應該改為,避免同時也有其他人再改一樣的值
this.setState((prevState, props) => {
  return {
    count: prevState.count + 1
  };
});

其他

  • radium
    • 在 js 樣式新增 :hover
  • css modules 自動升成唯一的 css 類名
  • HOC (High-Order Components) 高級元件 (react16)

    • aux

      • 不想要有一個空的 div 當根
      return (
        <div>
          <h1>title</h1>
          <p>i'm a pig.</p>
          <p>i'm 12 yeas old.</p>
        </div>
      );
      
      • 改用 aux
      const aux = props => props.children;
      
      export default aux;
      
      import Aux from "./hoc/aux";
      
      return (
        <Aux>
          <h1>title</h1>
          <p>i'm a pig.</p>
          <p>i'm 12 yeas old.</p>
        </Aux>
      );
      
  • prop-types

    • 用來確認 props 傳入的型態
    import PropTypes from 'prop-types';
    
    class Person extend Component {
        ...
    }
    
    Person.propTypes = {
        click: PropTypes.func,
        name: PropTypes.string,
        age: PropTypes.number
    }
    
    • 設定預設值
    import PropTypes from "prop-types";
    
    class Greeting extends React.Component {
      render() {
        return <h1>Hello, {this.props.name}</h1>;
      }
    }
    
    Greeting.defaultProps = {
      name: "Stranger"
    };
    
    ReactDOM.render(<Greeting />, document.getElementById("example"));
    
  • ref
    • 用來讓 input focus 之類的?
  • context (react16.3)

參考資料


Similar Posts

下一篇 ES6 學習筆記

Content