Bản thân React đã sử dụng những kỹ thuật để tối ưu hoá quá trình render UI, nhưng tuỳ vào độ phức tạp và business của app mà bản thân React không thể đáp ứng đủ tối ưu hoá quá trình render; vì vậy chúng ta cần implement những kỹ thuật để cải thiện performance của app.
Sử dụng shouldComponentUpdate
Thông thường các child components luôn luôn re-render lại theo parent component cho dù những props truyền vào cho các child components này không thay đổi.
Trong thực tế chúng ta chỉ cần render child components chỉ khi props truyền vào thay đổi, để làm được điều này chúng ta cần implement hàm shouldComponentUpdate
như sau:
1 2 3 4 5 6 7 | <span class="token function">shouldComponentUpdate</span><span class="token punctuation">(</span><span class="token parameter">nextProps<span class="token punctuation">,</span> nextState</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>nextProps<span class="token punctuation">.</span>data <span class="token operator">===</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>data<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">// skip re-render component</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token comment">// re-render component (default)</span> <span class="token punctuation">}</span> |
Trong hầu hết tất cả các trường hợp, thay vì ta implement hàm shouldComponentUpdate
manual, thì có thể kế thừa một class component từ PureComponent
thay vì Component
.
PureComponent
tương tự như shouldComponentUpdate
với shallow comparison của props, state
Tương tự với PureComponent
trong class component thì ta có thể sử dụng React.memo
trong functional component như sau:
1 2 3 4 5 6 | <span class="token keyword">function</span> <span class="token function">MyComponent</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/* render using props */</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">default</span> React<span class="token punctuation">.</span><span class="token function">memo</span><span class="token punctuation">(</span>MyComponent<span class="token punctuation">)</span><span class="token punctuation">;</span> |
Sử dụng useMemo, useCallback hooks trong functional component
Nếu app có những data cần tính toán phức tạp thì ta cần cached (memorized) những data này để khỏi phải tính toán lại nếu input không thay đổi.
useMemo
1 2 | <span class="token keyword">const</span> memoizedValue <span class="token operator">=</span> <span class="token function">useMemo</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">computeExpensiveValue</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>a<span class="token punctuation">,</span> b<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
useMemo
chỉ thực hiện computeExpensiveValue
nếu a
hoặc b
thay đổi.
Chúng ta cũng có thể apply useMemo
để cached một react component như sau:
1 2 | <span class="token keyword">const</span> memoizedGreeting <span class="token operator">=</span> <span class="token function">useMemo</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token operator"><</span>div<span class="token operator">></span>Hello <span class="token punctuation">{</span>name<span class="token punctuation">}</span><span class="token operator">!</span><span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span><span class="token punctuation">,</span> <span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
useCallback
useMemo
sử dụng để cached value, còn useCallback
dùng để cached một callback
function
Như vậy ta có thể sử dụng useCallback
để cached một callback
funtion không thay đổi reference trong mỗi lần render
1 2 3 4 5 6 7 | <span class="token keyword">const</span> memoizedCallback <span class="token operator">=</span> <span class="token function">useCallback</span><span class="token punctuation">(</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">doSomething</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>a<span class="token punctuation">,</span> b<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> |
Virtualize Long Lists
Đây là kỹ thuật tối ưu performance nếu render một list data dài và phức tạp. Kỹ thuật này chỉ render một nhóm các item trong list ra trên UI chứ không render toàn bộ list data
Có nhiều libs support kỹ thuật này, mà điển hình là react-window và react-virtualized , các libs này cung cấp các components cho việc hiển thị list, grid, table.
Sử dụng Production Build
Khi release một react app chúng ta cần build ở mode production
, việc này đảm bảo version react sẽ được loại bỏ các warning không cần thiết, các đoạn code debug, component, tools support khi dev và giảm build size,…
Sử dụng build file:
1 2 3 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__">[email protected]</a>/umd/react.production.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script" /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__">[email protected]</a>/umd/react-dom.production.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script" /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> |
webpack:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">const</span> TerserPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'terser-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span> mode<span class="token operator">:</span> <span class="token string">'production'</span><span class="token punctuation">,</span> <span class="token comment">// important</span> optimization<span class="token operator">:</span> <span class="token punctuation">{</span> minimizer<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token keyword">new</span> <span class="token class-name">TerserPlugin</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token comment">/* additional options here */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
Kết luận
Trên đây là một số điểm cần lưu ý để cải thiện performance của react app, một số kỹ thuật nữa sẽ có trong phần tiếp theo, các bạn đón đọc nhé, xin cám ơn!