CLASSFUNC BLOG
We Share Our Knowledge
Performance React App Với React.memo , useMemo , useCallback
JavaScriptReactJS
A Phi
22 Th02 2021 08:03

1. Re-render và React.memo

`React.memo ` là 1 HOC( higher order component). `React.memo` là một chức năng cho phép tối ưu hóa cách các component được render .

Ví Dụ:

function App() { const [skill, setSkill] = React.useState('') const [skills, setSkills] = React.useState([ 'HTML', 'CSS', 'JavaScript' ]) function handleChangeInput(event) { setSkill(event.target.value); } function handleAddSkill() { setSkills(skills.concat(skill)) } return ( <> <input onChange={handleChangeInput} /> <button onClick={handleAddSkill}>Add Skill</button> <SkillList skills={skills} /> </> ); } const SkillList = React.memo(({ skills }) => { console.log('rerendering'); return ( <ul> {skills.map((skill, i) => <li key={i}>{skill}</li>)} </ul> ) }) export default App

Khi không sử dụng `React.memo` SkillList sẽ bị re-render mỗi lần thay đổi giá trị input.

`React.memo` thực hiện một quá trình được gọi là memoization giúp ngăn các component re-render khi không cần thiết ( props không thay đổi thì không cần re-render ).

`React.memo` sẽ chỉ render lại component nếu props thay đổi và sử dụng pattern shallowly compare.Vì vậy nếu trong component sử dụng useState hay useContent thì component vẫn sẽ re-render khi state hoặc context thay đổi. Shallowly compare chỉ kiểm tra các key , value giữa prevProps và nextProps nên khi component trở nên phức tạp , dữ liệu nhiều tầng bạn có thể custom comparison

function MyComponent(props) { /* render sử dụng props */ } function areEqual(prevProps, nextProps) { /* trả về true khi prevProps = nextProps // ko cần re-render ngược lại trả về false */ } export default React.memo(MyComponent, areEqual);

2. useMemo

useMemo để lưu trữ kết quả của các phép tính tốn kém tài nguyên. quá trình này là `Memoization`. Khi quá trình `Memoization` được thực hiện, nó sẽ tính toán và lưu kết quả cho từng bộ input và khi gặp lại bộ input đã từng thực hiện thì nó sẽ không tính toán nữa mà trả về kết quả có sẵn luôn.

useMemo cho phép chúng ta memoize , hoặc ghi nhớ kết quả của phép tính phức tạp khi phép tính đó đã được thực hiện.

useMemo trả về một giá trị từ phép tính, sau đó được lưu trữ trong một biến.

useMemo tạo ra một memoized value và chỉ tính toán ra value mới khi dependencies thay đổi. Nó nhận vào 2 tham số là function và dependencies. Nó trả về memoized value và chỉ tính toán value mới khi dependencies thay đổi. Nếu dùng empty dependencies thì không bao giờ tính toán lại value mới.

Ví Dụ :

function App() { const [skill, setSkill] = React.useState('') const [skills, setSkills] = React.useState([ 'HTML', 'CSS', 'JavaScript', ...thousands more items ]) function handleChangeInput(event) { setSkill(event.target.value); } function handleAddSkill() { setSkills(skills.concat(skill)) } const handleRemoveSkill = React.useCallback((skill) => { setSkills(skills.filter(s => s !== skill)) }, [skills]) return ( <> <SearchSkills skills={skills} /> <input onChange={handleChangeInput} /> <button onClick={handleAddSkill}>Add Skill</button> <SkillList skills={skills} handleRemoveSkill={handleRemoveSkill} /> </> ); } function SearchSkills() { const [searchTerm, setSearchTerm] = React.useState(''); const searchResults = React.useMemo(() => { return skills.filter((s) => s.includes(searchTerm); }), [searchTerm]); function handleSearchInput(event) { setSearchTerm(event.target.value); } return ( <> <input onChange={handleSearchInput} /> <ul> {searchResults.map((result, i) => <li key={i}>{result}</li> </ul> </> ); } export default App

useMemo được sử dụng như 1 cách tối ưu hoá hiệu suất , không có sự đảm bảo chắn chắn nào các giá trị sẽ không bị tính lại vì React có thể xoá những cặp dữ liệu đã được ghi nhớ để giải phóng bộ nhớ. khi đó những kết quả này cần được tính lại 1 lần nữa

3. useCallback

useCallback là một hook được sử dụng để cải thiện hiệu suất component.

useCallback giúp tạo ra một memoized callback và chỉ tạo ra callback mới khi dependencies thay đổi. Nó nhận vào 2 tham số là "function" và "dependencies". Nó trả về là memoized callback

useCallback chỉ tạo ra function mới khi dependencies thay đổi. Nếu dùng empty dependencies thì chỉ tạo ra 1 callback 1 lần duy nhất. nếu không có dependencies thì callback sẽ dc tạo mới mỗi lần re-render.

useCallback là chức năng theo cách tương tự như React.memo hoạt động. Nó memoize các function callback, vì vậy nó không được tạo lại trên mỗi lần render.

Ví Dụ :

function SearchEvents() { const handleSearch = useCallback(() => {}, []) return <Search onChange={handleSearch} />; }

Mỗi lần SearchEvents re-render do có useCallback() nó chỉ tạo function một lần đầu và Search không bị re-render.

Cảm ơn các bạn đã xem bải viết. Chúc các bạn thành công .

Tham khảo thêm :

  1. https://reactjs.org/docs/hooks-reference.html
  2. https://reactjs.org/docs/react-api.html
  3. https://reactjs.org/docs/shallow-compare.html