React strict mode (chế độ phát triển) trong React
- 04-10-2022
- Toanngo92
- 0 Comments
Tháng 8 năm 2018, React React bổ sung Component <React.StrictMode />
, vì lí do đó, khi khởi tạo bất kì dự án nào của React, trong file index.js của ứng dụng luôn luôn bắt đầu với cấu trúc như sau:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Để hiểu vấn đề này, chúng ta cần tìm hiểu rõ hơn về Life Cycle trong React:
Ở các phiên bản trước, nhận ra sự phức tạp của vòng đời React, component có thể mount, rồi unmount lại nhiều lần mà vẫn giữ nguyên state trước đó, và có nhiều tình huống useEffect bị gọi lại nhiều lần gây lỗi logic, nên từ phiên bản React 18 trở đi, chế độ này được React phát triển với kì vọng giúp các developer kiểm tra trước các vấn đề trong môi trường development, (khi component được mount lại sau khi unmount có gây ảnh hưởng tới state không) nhằm hỗ trợ các developer cũ dễ dàng update phiên bản và giúp nhận diện các lỗi dễ phát sinh trong quá trình phát triển.
Vậy tại sao phải quan tâm tới chế độ này ?
Mục lục
Strict Mode sẽ chạy code 2 lần
Đây là một vấn đề ai tiếp cận ReactJS với dự án mới gần đây đều gặp phải (bao gồm cả mình). Chế độ nghiêm ngặt của React thực hiện là chạy một số method (phương thức)/ callback (lệnh gọi lại) nhất định hai lần (CHỈ ở chế độ DEV). Các method, callback sau sẽ được chạy hai lần ở Chế độ nghiêm ngặt (CHỈ ở chế độ DEV):
- Class component constructor method
- Render method (bao gồm function component)
- setState updater functions (tham số đầu tiên)
- static getDerivedStateFromProps lifecycle
- React.useState state initializer callback function
- The React.useMemo callback
React làm điều này vì nó không thể cảnh báo bạn một cách đáng tin cậy về các tác dụng phụ mà bạn thực hiện trong các phương pháp đó. Nhưng nếu những phương thức đó là không cần thiết, thì việc gọi chúng nhiều lần sẽ không gây ra bất kỳ rắc rối nào.
Lưu ý rằng các lệnh gọi lại useEffect và useLayoutEffect không được gọi hai lần ngay cả trong chế độ nhà phát triển + chế độ nghiêm ngặt vì toàn bộ điểm của các lệnh gọi lại đó là thực hiện các tác dụng phụ.
Lưu ý :
useEffect và useLayoutEffect không được gọi hai lần trong chế độ nhà phát triển.
useReducer bạn truyền cho React.useReducer cũng không được gọi hai lần trong chế độ nhà phát triển.
Tất nhiên, khi deploy ứng dụng bằng script build, tất cả các cảnh báo sẽ biến mất và lệnh gọi lại chỉ được gọi một lần. Điều này là do những thứ này chỉ ở đó để giúp bạn trong quá trình phát triển và sẽ không ảnh hưởng đến ứng dụng trong môi trường production.
Giải quyết vấn đề code chạy 2 lần
Tham khảo tại Stack Overflow (reducer function is being called twice)
Để giải quyết vấn đề này, việc đơn giản và hay sử dụng nhất trong thực tế là chúng ta cần loại bỏ cấu trúc <React.StrictMode> đang bọc component <App/> trong file index.js và chỉ sử dụng nó trong quá trình phát triển tính năng mới để debug ứng dụng. Ví dụ:
function App() {
return (
<div>
<SomeComponent />
<React.StrictMode>
<SomeNewFeature />
</React.StrictMode>
<SomeComponent />
</div>
)
}
Bạn có thể sử dụng ở bất kỳ đâu trong ứng dụng của mình ở bất kỳ độ sâu nào. Đây có thể là một cách tuyệt vời để chọn một số phần nhất định của ứng dụng của bạn vào chế độ nghiêm ngặt mà không nhận được rất nhiều cảnh báo ở khắp mọi nơi. Chúc bạn thành công !