如何使用 React Hooks 实现深色模式
深色模式是目前应用和网站广泛采用的最新功能之一。深色可以延长移动设备的电池续航时间。据谷歌称,YouTube 应用的深色模式在 50% 亮度下可节省 15% 的电量,在 100% 亮度下则可节省高达 60% 的电量。苹果公司已确认,从 2020 年起,其手机将全部采用 OLED 屏幕。
为什么选择 React Hooks?
我们知道 React 组件支持自上而下的数据流,这有助于我们将应用程序组织成易于管理的小 UI 单元。然而,如果仅使用组件模型,组件会变得庞大且难以重构。此外,组件之间可能存在逻辑重复的情况。Hooks 的优势在于,它允许我们将组件内的逻辑组织成易于复用的独立单元。
然而,我们常常无法进一步分解复杂的组件,因为其逻辑是有状态的,无法提取到函数或其他组件中。——丹·阿布拉莫夫
实现钩子
为了简化演示如何在React Hooks中实现深色模式,我们将使用localStorage,以便浏览器在页面重新加载时记住用户的偏好设置。在更复杂的 Web 应用中,用户的偏好设置可以存储在数据库中。那么,让我们从 Facebook 的标准 React 样板代码开始。克隆仓库,切换到新创建的项目文件夹,然后运行应用程序。更多信息,请参阅文档。
npx create-react-app dark-mode;
cd dark-mode;
npm start;
接下来,我们来添加 CSS 颜色变量。我们可以先从一种颜色和一个背景色开始,但如果您想构建一个更大的配色方案,可以添加更多变量。这样,我们就以一种一致的方式模块化了颜色样式,可以轻松地在整个网站中实现。
// App.css
...
html[data-theme="light"] {
--color: rgb(5, 5, 5);
--background-color: rgb(250, 250, 250);
}
html[data-theme="dark"] {
--color: rgb(250, 250, 250);
--background-color: rgb(5, 5, 5);
}
...
要设置变量,请按如下方式替换App.css文件中的header CSS :
// App.css
...
.App-header {
background-color:var(--background-color);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color:var(--color);
}
...
创建主题切换组件
在 src* 文件夹中创建一个新文件,并将其命名为 **ThemeToggle**或类似名称。目前这是一个入门项目,如果您愿意,可以创建一个单独的ThemeToggle目录。在这里,我们将使用useState hook 来存储当前主题偏好设置。
// ThemeToggle.js
...
const ThemeToggle = () => {
const [darkMode, setDarkMode] = useState(
localStorage.getItem("theme") === "dark" ? true : false
);
useEffect(() => {
document
.getElementsByTagName("HTML")[0]
.setAttribute("data-theme", localStorage.getItem("theme"));
}, []);
};
...
如果用户是首次访问该网站,localStorage中不会设置任何偏好设置。我们的严格相等性比较运算符将返回false,并调用darkMode钩子将浅色主题应用于整个应用程序。
这是通过 HTML 的data- 属性实现的,它允许我们将信息存储在语义化的 HTML 元素中。我们将在用于切换主题(深色或浅色)的方法中使用它。使用相同的逻辑,我们也可以调用之前设置的setDarkMode钩子函数,将主题信息存储在localStorage中。
// ThemeToggle.js
...
const switchThemes = () => {
if (isDark === false) {
localStorage.setItem("theme", "dark");
document
.getElementsByTagName("HTML")[0]
.setAttribute("data-theme", localStorage.getItem("theme"));
setDarkMode(true);
} else {
localStorage.setItem("theme", "light");
document
.getElementsByTagName("HTML")[0]
.setAttribute("data-theme", localStorage.getItem("theme"));
setDarkMode(false);
}
};
...
在ThemeToggle中,我们需要做的最后一件事是返回要导入的按钮。
// ThemeToggle.js
...
return (
<label className="switch">
<input
type="checkbox"
defaultChecked={isDark}
onChange={() => toggleThemeChange()}
/>
<span className="slider round" />
</label>
);
...
现在,为了进行测试,我们可以将其导入到我们的App.js中。
// App.js
...
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
React Hooks Dark Mode Starter
</p>
<ThemeToggle />
</header>
</div>
);
}
...
恭喜!!
现在,您有了一个可用的元素,可以将其放置在应用程序中的任何位置。如果您想查看完整代码或创建自己的分支,请访问我的代码仓库(链接在此)。
原文发布于https://www.josephc.how/react-hooks-dark-mode/
文章来源:https://dev.to/chowjiaming/how-to-do-dark-mode-with-react-hooks-23gi