- vừa được xem lúc

Tối ưu hóa hiệu năng ứng dụng React nâng cao.

0 0 32

Người đăng: Nhật Ngô Sách

Theo Viblo Asia

React rất là nhanh. Mình thực sự thấy nó rất nhanh. Đó là điều làm cho React thực sự tuyệt vời.

Nhưng nếu bạn muốn tối ưu hóa ứng dụng của bạn thì có một số cách bạn có thể làm.

Hôm nay chúng ta sẽ thấy 2 công nghệ hữu dụng nhất được React cung cấp sẽ giải quyết những vấn đề về hiệu năng như thế nào.

1. Bắt đầu với một ví dụ đơn giản.

Lấy một ví dụ đơn giản, chúng ta có một component Display hiển thị một dòng văn bản.

Component này là con của component Controller, trong đó Controller còn chứa một nút có tác dụng làm tăng giá trị biến count trong state khi được click vào.

import React, { useState } from 'react'; const Controller = () => { const [count, setCount] = useState(0); return ( <> <button onClick={() => setCount(count => count + 1)}>Click</button> <Display /> </> );
}; const Display = () => { console.log('display is re-rendering'); return ( <>This is a display function </> );
};

Chúng ta thêm console.log(...) vào để phát hiện component Display của chúng ta có bị render lại hay không.

Bây giờ, khi chúng ta click vào button bên trong Controller và mở console.

Mặc dù chúng ta không hề tác động gì tới component Display nhưng mà nó luôn bị render lại mỗi khi chúng ta click vào button.

Điều này không hề ổn một chút nào. Điều gì sẽ xảy ra nếu chúng ta sử dụng component Display này ở trên toàn bộ project?

Hiệu năng sẽ hoàn toàn bị phá vỡ.

2. Memoization là gì ?

Memoization là một kĩ thuật quen thuộc được sử dụng ở rất nhiều nơi. Nó cũng không có gì ngoài bộ nhớ đệm (caching).

Theo Wikipedia nó được định nghĩa như sau :

In computing, memoization or memoisation is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.

Như vậy, Nếu memoization là một kĩ thuật giúp cải thiện hiệu năng cho các hàm (function), chúng ta có thể ứng dụng nó cho functional component hay không ?

Yes, rất may chúng ta có thể làm nó. React cung cấp cho chúng ta một tính năng được gọi là React.memo()

Bây giờ, chúng ta hãy xem cách để giải quyết vấn đề trên.

3. Sử dụng React.memo() để chặn render lại (re-render).

React.memo() nhận vào 2 tham số :

  • Đầu tiên là hàm mà chúng ta muốn ghi nhớ (memorize).
  • Thứ 2 là hàm có chức năng giống như shouldComponentUpdate() (optional). Chúng ta sẽ gọi nó sau,

Bây giờ, nhìn xem điều gì sẽ xảy ra nếu chúng ta viết lại component Display như sau ...

import React,{useState , memo} from 'react'; const Display = memo(() => { console.log('display is re-rendering'); return ( <div> This is a display function.</div> )
})

Thật tuyệt vời, component của chúng ta đã không bị render lại mỗi khi click vào button.

4. Hãy tiến thêm một bước nữa.

Okey, bây giờ chúng ta đã có một component tối ưu. Nhưng vấn đề là component này thật ngu ngốc, nó chỉ hiển thị một dòng text. chả có tác dụng gì cả. Tôi muốn nội dung của Display phụ thuộc vào một vài props truyền vào nó.

Bây giờ sẽ viết lại component Display cho nó hiển thị một danh sách tên người.

Mỗi khi click vào button sẽ thêm một cái tên mới vào state.

import React,{useState , memo} from 'react'; const Controller = () => { const [names , setNames] = useState([]); const addName = () => { const newNames = names; newNames.push('another name') setNames(newNames); } return <> <button onClick={() => addName()}> Add Name </button> <Display names={names}/> </>
}; const Display = memo((props) => { return <div> {props.names.map(name => <div>{name}</div>)} </div>
});

Chúng ta sẽ nhìn thấy another name được thêm vào danh sách tên mỗi lần click vào button Add Name.

Nhưng không có gì xảy ra cả. Tại sao vậy ? Chúng ta sẽ giải đáp thắc mắc này trong phần tiếp theo.

5. Mutable vs Immutable.

Để giải quyết vấn đề này, chúng ta phải thực sự hiểu về Immutable ( tính bất biến )

Ở dòng newNames = names, chúng ta nghĩ rằng gắn names cho biến mới newNames nhưng thực sự arrays trong Javascript không làm việc như vậy.

Khi thực hiện dòng lệnh trên, nó sẽ gán tham chiếu của mảng names cho newNames. Nên kết quả là nội dung của mảng names thay đổi nhưng tham chiếu không hề thay đổi.

Và tất nhiên chúng ta đều biết React chỉ re-render lại khi state thay đổi nên việc chạy hàm addName() kia hoàn toàn không có tác dụng.

Chúng ta giải quyết vấn đề này bằng các viết lại hàm addName() như sau ...

const addName = () => { const newNames = [...names]; // SEE HERE newNames.push('another name'); setNames(newNames);
}

Toán tử ... (spread operator) trả về một mảng mới và gán cho newNames.

Bây giờ nếu chúng ta click vào button, chúng ta có thể thấy component đã được render lại.

6. Khi React.memo không được, hãy sử dụng useCallback() để giải quyết.

Vòa một ví dụ khác. Chúng ta tạo một component tương tự ví dụ trước, sẽ thêm một cái tên mới mỗi khi click vào button.

Và chúng ta có một component khác để xóa danh sách tên trên.

import React,{useState , memo} from 'react'; const Controller = () => { const [names , setNames] = useState([]); const addName = () => { const newNames = [...names]; newNames.push('another name'); setNames(newNames); }; const clearNames = () => setNames([]); return <> <button onClick={() => addName()}> Add Name </button> <div>{names.map(name => <div>{name}</div>)}</div> <ClearButton clearNames={clearNames}/> </>
}; const ClearButton = memo((props) => { return <div> <button onClick={props.clearNames}> Clear</button> </div>
});

Bây giờ, chúng ta click vào button Add Name. Component ClearButton đã bị render lại, điều này là không cần thiết.

Để giải quyết vấn đề này chúng ta có thể sử dụng một hook tên là useCallback(). Cái hook useCallback() này giúp chúng ta ngăn chặn việc tính toán lại (re-computing) clearNames. Nó được cung cấp bởi React và có thể import như sau ...

import React,{ useCallback} from 'react';

Và chúng ta có thể viết lại hàm clearNames như sau ...

const clearNames = useCallback(() => setNames([]), [setNames]);

Yeee, vấn đề của chúng ta không còn nữa !

Tổng kết lại thì trên đây là một số các bạn có thể sử dụng để cải thiện ứng dụng React của mình. Nhưng những điều tốt đẹp thì thường đi cùng cạm bẫy. Nên hãy cố gắng sử dụng khôn ngoan để tránh ăn bug nhé các bạn. ???

Còn các bạn làm gì để tối ưu hiệu năng ứng dụng React, hãy comment cho mình và mọi người tham khảo nhé! Happy Coding!

Tìm hiểu thêm :

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cùng tìm hiểu về các hook trong React hooks

Đối với ai đã từng làm việc với React thì chắc hẳn đã có những lúc cảm thấy bối rối không biết nên dùng stateless (functional) component hay là stateful component. Nếu có dùng stateful component thì cũng sẽ phải loay hoay với đống LifeCycle 1 cách khổ sở Rất may là những nhà phát triển React đã kịp

0 0 81

- vừa được xem lúc

Khi nào nên (và không nên) sử dụng Redux

. Công việc quản lý state với những hệ thống lớn và phức tạp là một điều khá khó khăn cho đến khi Redux xuất hiện. Lấy cảm hứng từ design pattern Flux, Redux được thiết kế để quản lý state trong các project JavaScript.

0 0 106

- vừa được xem lúc

ReactJS: Props và State

Nếu bạn đã học ReactJS hay React Native, bạn sẽ thấy các Props và State được sử dụng rất nhiều. Vậy chính xác chúng là gì? Làm thế nào để chúng ta sử dụng chúng đúng mục đích đây.

0 0 41

- vừa được xem lúc

State và Props trong Reactjs

Hello các bạn, tiếp tục seri tìm hiểu về ReactJs hôm nay mình xin giới thiệu đến các bạn hai thứ mình cho là thú vị nhất của ReactJs là State và Props. State bạn có thể hiểu đơn giản là một nơi mà bạn lưu trữ dữ liệu của Component, từ đó bạn có thể luân chuyển dữ liệu đến các thành phần trong Compon

0 0 36

- vừa được xem lúc

Memoization trong React

. 1.Introduction. Memoization có liên quan mật thiết đến bộ nhớ đệm, và dưới đây là một ví dụ đơn giản:. const cache = {}.

0 0 38

- vừa được xem lúc

Nâng cao hiệu suất React Hooks với React.memo, Memoization và Callback Functions

1.Ngăn Re-render và React.memo. React.

0 0 67