Cách tạo Dark Mode trong React mà không cần sử dụng React Context

Việc các ứng dụng có cài đặt cho phép bạn chuyển đổi giữa chế độ tối và sáng đã trở nên phổ biến. Có thể do sự phổ biến của giao diện người dùng tối, có thể là do các ứng dụng đang dần trở nên dễ cấu hình hơn.
React context là một cách dễ dàng để chia sẻ dữ liệu trên toàn cầu, nhưng nó có thể khiến việc tái sử dụng thành phần trở nên khó khăn hơn. Thay vào đó, bạn có thể xây dựng một thành phần nút chế độ tối sử dụng hook useEffect và useState thay vì ngữ cảnh. Nó sẽ chuyển đổi một thuộc tính dữ liệu trên phần tử body mà các kiểu CSS có thể nhắm mục tiêu.
Mục Lục
Những gì bạn cần
Để làm theo hướng dẫn này, bạn sẽ cần những thứ sau:
- Phiên bản gần đây của Node được cài đặt trên máy của bạn.
- Hiểu biết cơ bản về React và React hooks.
- Một dự án React mới bắt đầu. Chỉ cần tạo một ứng dụng React và bạn đã sẵn sàng.
Tạo một thành phần nút
Thành phần nút sẽ chịu trách nhiệm chuyển đổi chủ đề từ tối sang sáng. Trong một ứng dụng thực, nút này có thể là một phần của thành phần Navbar.
Trong thư mục src, tạo một tệp mới có tên là Button.js và thêm đoạn mã sau.
import { useState } from 'react'export default function Button() {
const [theme, settheme] = useState("dark")
const handleToggle = () => {
const newTheme = theme === "light" ? "dark" : "light"
settheme(newTheme)
}
return (
<>
<button className="themeBtn" onClick={handleToggle}>
{theme=== "light" ? <span>dark</span> : <span>light</span>}
</button>
</>
)
}
Đầu tiên, nhập hook useState () từ React. Bạn sẽ sử dụng nó để theo dõi chủ đề hiện tại.
Trong thành phần Nút, khởi tạo trạng thái tối. Hàm handleToggle () sẽ đảm nhận chức năng chuyển đổi. Nó chạy mỗi khi nút được nhấp.
Thành phần này cũng chuyển đổi văn bản nút khi nó thay đổi chủ đề.
Để hiển thị thành phần Nút, hãy nhập thành phần đó vào App.js.
import Button from './Button';
function App() {
return (
<div>
<Button/>
</div>
);
}export default App;
Tạo kiểu CSS
Ngay bây giờ, nhấp vào nút không thay đổi giao diện người dùng của ứng dụng React. Để làm được điều đó, trước tiên bạn sẽ cần tạo các kiểu CSS cho chế độ tối và sáng.
Trong App.css, hãy thêm phần sau.
body {
--color-text-primary:
--color-text-secondary:
--color-bg-primary:
--color-bg-secondary:
background: var(--color-bg-primary);
color: var(--color-text-primary);
transition: background 0.25s ease-in-out;
}
body[data-theme="light"] {
--color-text-primary:
--color-bg-primary:
}
body[data-theme="dark"] {
--color-text-primary:
--color-bg-primary:
}
Tại đây, bạn đang xác định kiểu của phần tử body bằng cách sử dụng các thuộc tính dữ liệu. Có thuộc tính dữ liệu chủ đề sáng và thuộc tính dữ liệu chủ đề tối. Mỗi người trong số họ có các biến CSS với các màu khác nhau. Sử dụng thuộc tính dữ liệu CSS sẽ cho phép bạn chuyển đổi kiểu theo dữ liệu. Nếu người dùng chọn chủ đề tối, bạn có thể đặt thuộc tính dữ liệu cơ thể thành màu tối và giao diện người dùng sẽ thay đổi.
Bạn cũng có thể sửa đổi các kiểu phần tử nút để thay đổi theo chủ đề.
.themeBtn {
padding: 10px;
color: var(--color-text-primary);
background: transparent;
border: 1px solid var(--color-text-primary);
cursor: pointer;
}
Sửa đổi thành phần nút để chuyển đổi kiểu
Để chuyển đổi các kiểu được xác định trong tệp CSS, bạn sẽ cần đặt dữ liệu trong phần tử body trong hàm handleToggle ().
Trong Button.js, sửa đổi handleToggle () như sau:
const handleToggle = () => {
const newTheme = theme ==="light" ? "dark" : "light"
settheme(newTheme)
document.body.dataset.theme = theme
}
Nếu bạn nhấp vào nút, nền sẽ chuyển từ tối sang sáng hoặc sáng sang tối. Tuy nhiên, nếu bạn làm mới trang, chủ đề sẽ đặt lại. Để duy trì cài đặt chủ đề, hãy lưu trữ tùy chọn chủ đề trong bộ nhớ cục bộ.
Sở thích người dùng lâu dài trong bộ nhớ cục bộ
Bạn nên truy xuất tùy chọn người dùng ngay sau khi thành phần Nút hiển thị. Hook useEffect () là hoàn hảo cho việc này vì nó chạy sau mỗi lần render.
Trước khi truy xuất chủ đề từ bộ nhớ cục bộ, trước tiên bạn cần lưu trữ chủ đề đó.
Tạo một hàm mới có tên storeUserPreference () trong Button.js.
const storeUserSetPreference = (pref) => {
localStorage.setItem("theme", pref);
};
Hàm này nhận tùy chọn người dùng làm đối số và lưu trữ nó dưới dạng một mục được gọi là chủ đề.
Bạn sẽ gọi hàm này mỗi khi người dùng chuyển đổi chủ đề. Vì vậy, hãy sửa đổi hàm handleToggle () để trông giống như sau:
const handleToggle = () => {
const newTheme = theme === "light" ? "dark" : "light"
settheme(newTheme)
storeUserSetPreference(newTheme)
document.body.dataset.theme = theme
}
Hàm sau lấy chủ đề từ bộ nhớ cục bộ:
const getUserSetPreference = () => {
return localStorage.getItem("theme");
};
Bạn sẽ sử dụng nó trong hook useEffect để mỗi khi thành phần hiển thị, nó sẽ tìm nạp tùy chọn từ bộ nhớ cục bộ để cập nhật chủ đề.
useEffect(() => {
const userSetPreference = getUserSetPreference();if (userSetPreference) {
settheme(userSetPreference)
}
document.body.dataset.theme = theme
}, [theme])
Nhận Sở thích Người dùng Từ Cài đặt Trình duyệt
Để có trải nghiệm người dùng tốt hơn, bạn có thể sử dụng ưu tiên phối màu Tính năng phương tiện CSS để đặt chủ đề. Điều này phải phản ánh cài đặt hệ thống của người dùng mà họ có thể kiểm soát thông qua hệ điều hành hoặc trình duyệt của họ. Cài đặt có thể là sáng hoặc tối. Trong ứng dụng của bạn, bạn cần kiểm tra cài đặt này ngay lập tức sau khi thành phần nút tải. Điều này có nghĩa là triển khai chức năng này trong hook useEffect ().
Đầu tiên, hãy tạo một hàm truy xuất tùy chọn của người dùng.
Trong Button.js, hãy thêm phần sau.
const getMediaQueryPreference = () => {
const mediaQuery = "(prefers-color-scheme: dark)";
const mql = window.matchMedia(mediaQuery);
const hasPreference = typeof mql.matches === "boolean";if (hasPreference) {
return mql.matches ? "dark" : "light";
}
};
Tiếp theo, sửa đổi hook useEffect () để truy xuất tùy chọn truy vấn phương tiện và sử dụng nó nếu không có chủ đề nào được đặt trong bộ nhớ cục bộ.
useEffect(() => {
const userSetPreference = getUserSetPreference();
const mediaQueryPreference = getMediaQueryPreference();if (userSetPreference) {
settheme(userSetPreference)
} else {
settheme(mediaQueryPreference)
}
document.body.dataset.theme = theme
}, [theme])
Nếu bạn khởi động lại ứng dụng của mình, chủ đề phải phù hợp với cài đặt hệ thống của bạn.
Sử dụng React Context để chuyển đổi chế độ tối
Bạn có thể sử dụng thuộc tính dữ liệu, CSS và móc React để chuyển đổi chủ đề của ứng dụng React.
Một cách tiếp cận khác để xử lý chế độ tối trong React là sử dụng API ngữ cảnh. Bối cảnh React cho phép bạn chia sẻ dữ liệu giữa các thành phần mà không cần phải chuyển nó qua các đạo cụ. Khi sử dụng nó để chuyển đổi chủ đề, bạn tạo một ngữ cảnh chủ đề mà bạn có thể truy cập trong toàn bộ ứng dụng. Sau đó, bạn có thể sử dụng giá trị chủ đề để áp dụng các kiểu phù hợp.
Mặc dù cách tiếp cận này hoạt động, nhưng việc sử dụng các thuộc tính dữ liệu CSS đơn giản hơn.