可使用react自帶的Component Profiling工具,在頁面的url後面添加"?react_perf",就能夠在chrome的調試器裏面使用Performance tab頁記錄性能。react
經過觀察性能的瓶頸,咱們找出能夠優化的地方。仔細分析瓶頸產生的緣由,咱們而已藉助高階函數HOC 給想要優化的組件添加console.log().git
咱們知道,組件從新渲染的代價比較高。尤爲是包含不少子組件的外層組件,那麼咱們能夠在外層組件渲染的時候打印出來。實現方法:github
// in src/log.js
const log = BaseComponent => props => {
console.log(`Rendering ${BaseComponent.name}`);
return <BaseComponent {...props} />;
}
export default log;
// in src/MyComponent.js
import log from './log';
export default log(MyComponent);複製代碼
這樣咱們能夠觀察組件是否頻繁被從新渲染。chrome
有的時候父組件的一部份內容能夠提取一個子組件出來。而後咱們觀察這個子組件是否具備獨立的更新特徵,當子組件的數據沒有變化的時候,咱們使用 shouldComponentUpdate 來避免沒必要要的從新渲染。
當使用shouldComponentUpdate 方法的時候,咱們能夠考慮使用PureComponent。 注意PureComponent使用的是淺比較(===)。api
Recompose 是一個React的工具庫,提供了大量的函數式組件和高階組件。幫助你簡化定義React 組件,使用相似純函數組件定義出普通的React組件。具體的api參考官網。數組
當你使用Redux的時候,connect的Component默認是PureComponent方式,你所要作的是Redux判斷組件的props是否相等,用的是===,因此要注意可變對象和不可變對象的合理使用。在reducers裏面必定要使用不可變對象定義方式修改全局state,這樣才能真正從新選擇組件。bash
爲了不Redux在connect的時候沒必要要的從新render,要確保mapStateToProps方法在調用的時候不會產生一個新的object。例如不要再用{...object} 或者Object.assign()定義一個新的對象。
進一步可使用reselect庫。函數
在JSX中避免使用{{}}方式直接定義object。由於這種方式每次都會產生一個新數據。工具
//bad
import React from 'react';
import MyTableComponent from './MyTableComponent';
const Datagrid = (props) => (
<MyTableComponent style={{ marginTop: 10 }}>
...
</MyTableComponent>
)
//good
import React from 'react';
import MyTableComponent from './MyTableComponent';
const tableStyle = { marginTop: 10 };
const Datagrid = (props) => (
<MyTableComponent style={tableStyle}>
...
</MyTableComponent>
)複製代碼
// bad
const MyComponent = (props) => <div>{React.cloneElement(Foo, { bar: 1 })}</div>;
// good
const additionalProps = { bar: 1 };
const MyComponent = (props) => <div>{React.cloneElement(Foo, additionalProps)}</div>;複製代碼
當一個父組件中有純函數定義的組件時,合理使用compose的onlyUpdateForKeys。避免子組件沒必要要的從新render。性能
import { CardActions } from 'material-ui/Card';
import { CreateButton, RefreshButton } from 'admin-on-rest';
import onlyUpdateForKeys from 'recompose/onlyUpdateForKeys';
const Toolbar = ({ basePath, refresh }) => (
<CardActions>
<CreateButton basePath={basePath} />
<RefreshButton refresh={refresh} />
</CardActions>
);
export default onlyUpdateForKeys(['basePath', 'refresh'])(Toolbar);複製代碼
使用React開發項目,每當遇到性能瓶頸的時候,首先使用react-addons-perf來觀察瓶頸出現的地方,而後藉助輔助工具抽絲剝繭找出問題根源。最後使用shouldComponentUpdate等方式避免沒必要要的組件render,這種方式是最有效的。可是也要注意很小的組件調用pure()方法的開銷可能比從新渲染還要大,因此不要過分使用。