over 3 years ago

new Array()

範例

class Table extends PureComponent {
  render() {
return (
  <div>
    {this.props.items.map(i =>
      <Cell data={i} options={this.props.options || []} />
     )}
   </div>
 );
  }
}

每當執行 this.props.options || []
[] 如同 new Array() 會產生新的 array instance
導致淺層比對會一直出現 false 而讓每個 Cell components 每次都 re-render

修正

const default = [];
class Table extends PureComponent {
  render() {
    return (
      <div>
        {this.props.items.map(i =>
          <Cell data={i} options={this.props.options || default} />
         )}
       </div>
     );
  }
}

建立一個預設的 [] 來避免重複性的 re-render

new Function

範例

class App extends PureComponent {
  render() {
    return <MyInput
      onChange={e => this.props.update(e.target.value)} />;
  }
}
or
class App extends PureComponent {
  update(e) {
    this.props.update(e.target.value);
  }
  render() {
    return <MyInput onChange={this.update.bind(this)} />;
 }
}

如同 [] 上面兩種配置 function 的方式也會產生 new Function instance

修正

class App extends PureComponent {
  constructor(props) {
    super(props);
    this.update = this.update.bind(this);
  }
  update(e) {
    this.props.update(e.target.value);
  }
  render() {
    return <MyInput onChange={this.update} />;
  }
}

於 constructor 宣告配置 function 避開每次執行所產生的 new Function instance

使用 Reselect 配置 Redux connect(mapState)

範例

let App = ({otherData, resolution}) => (
  <div>
    <DataContainer data={otherData} />
    <ResolutionContainer resolution={resolution} />
  </div>
);
const doubleRes = (size) => ({
  width: size.width*2,
  height: size.height*2
});
App = connect(state => {
  return {
    otherData: state.otherData,
    resolution: doubleRes(state.resolution)
  }
})(App);

只要 otherData 一改變 DataContainer 和 ResolutionContainer component 就會跟著 render
即使 state.resolution 未做變動
那是因為 doubleRes function 永遠會return 一個 new resolution object

改用 reselect 優化 doubleRes function

import {createSelector} from “reselect”;
const doubleRes = createSelector(
  r => r.width,
  r => r.height,
  (width, height) => ({
    width: width*2,
    height: heiht*2
  })
);

Reselect 會記憶和 return 最後一次的資料
直到新的參數被更新

參考網址
https://medium.com/esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f#.rbs6epi7k@

← React Redux 自訂 Middleware 練習 React higher order components 驗證表單 →
 
comments powered by Disqus