การนำ Dark Mode ไปใช้ใน React Apps โดยใช้ styled-components

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างย่อ ↬ โหมดไลท์เป็นแบบแผนในเว็บและแอปบนอุปกรณ์เคลื่อนที่ส่วนใหญ่ อย่างไรก็ตาม ในการพัฒนาสมัยใหม่ เราได้เห็นแล้วว่าโหมดมืดซึ่งแสดงข้อความและองค์ประกอบส่วนต่อประสานบนพื้นหลังสีเข้มนั้นกลายเป็นความชอบของผู้ใช้อย่างรวดเร็ว ในบทความนี้ เราจะเรียนรู้วิธีใช้งานโหมดมืดอย่างมีประสิทธิภาพในแอป React บนเว็บเพจอย่างง่าย โดยใช้ไลบรารีที่มีสไตล์และใช้ประโยชน์จากคุณสมบัติ React บางอย่าง เช่น hooks เราจะพูดถึงข้อดีและข้อเสียของโหมดมืดและเหตุผลที่ควรใช้

หนึ่งในคุณสมบัติซอฟต์แวร์ที่ร้องขอบ่อยที่สุดคือโหมดมืด (หรือโหมดกลางคืนตามที่คนอื่นเรียก) เราเห็นโหมดมืดในแอพที่เราใช้ทุกวัน โหมดมืดกลายเป็นส่วนสำคัญสำหรับบริษัทที่ต้องการดูแลสายตาของผู้ใช้ตั้งแต่มือถือไปจนถึงเว็บแอป

โหมดมืดเป็นคุณสมบัติเสริมที่แสดงพื้นผิวที่มืดเป็นส่วนใหญ่ใน UI บริษัทใหญ่ๆ ส่วนใหญ่ (เช่น YouTube, Twitter และ Netflix) ได้นำโหมดมืดมาใช้ในแอพมือถือและเว็บ

แม้ว่าเราจะไม่เจาะลึกถึง React และ styled-components แต่ความรู้พื้นฐานเกี่ยวกับ React, CSS และ styled-components จะมีประโยชน์ กวดวิชานี้จะเป็นประโยชน์กับผู้ที่ต้องการปรับปรุงเว็บแอปพลิเคชันของตนโดยจัดไว้สำหรับผู้ที่รักโหมดมืด

StackOverflow ประกาศโหมดมืดบน Twitter
StackOverflow ประกาศโหมดมืดบน Twitter (ตัวอย่างขนาดใหญ่)

ไม่กี่วันก่อนเขียนบทความนี้ StackOverflow ได้ประกาศเปิดตัวโหมดมืด ให้ผู้ใช้มีโอกาสสลับไปมาระหว่างสองโหมด

โหมดมืดช่วยลดอาการปวดตาและช่วยให้คุณทำงานบนคอมพิวเตอร์หรือโทรศัพท์มือถือเป็นเวลานาน

โหมดมืดคืออะไร?

โหมดมืดคือชุดสีของอินเทอร์เฟซใดๆ ที่แสดงข้อความและองค์ประกอบอินเทอร์เฟซบนพื้นหลังสีเข้ม ซึ่งทำให้หน้าจอดูโทรศัพท์มือถือ แท็บเล็ต และคอมพิวเตอร์ง่ายขึ้นเล็กน้อย โหมดมืดช่วยลดแสงที่ปล่อยออกมาจากหน้าจอ ในขณะที่ยังคงอัตราส่วนคอนทราสต์สีขั้นต่ำที่จำเป็นสำหรับการอ่านได้

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

ทำไมคุณควรสนใจโหมดมืด?

โหมดมืดปรับปรุงการยศาสตร์ของภาพโดยลดอาการปวดตา ปรับหน้าจอให้เข้ากับสภาพแสงในปัจจุบัน และให้ความสะดวกในการใช้งานในเวลากลางคืนหรือในสภาพแวดล้อมที่มืด

ก่อนใช้งานโหมดมืดในแอปของเรา มาดูประโยชน์ของมันกันก่อน

ประหยัดพลังงาน

โหมดมืดในเว็บและแอปบนอุปกรณ์เคลื่อนที่สามารถยืดอายุแบตเตอรี่ของอุปกรณ์ได้ Google ได้ยืนยันว่าโหมดมืดบนหน้าจอ OLED นั้นช่วยยืดอายุแบตเตอรี่ได้อย่างมาก

ตัวอย่างเช่น ที่ความสว่าง 50% โหมดมืดในแอป YouTube จะประหยัดพลังงานหน้าจอมากกว่าพื้นหลังสีขาวเรียบประมาณ 15% ที่ความสว่างหน้าจอ 100% อินเทอร์เฟซมืดช่วยประหยัดพลังงานหน้าจอได้มากถึง 60%

โหมดมืดสวยงาม

โหมดมืดนั้นสวยงามและสามารถเพิ่มความน่าดึงดูดของหน้าจอได้อย่างมาก

แม้ว่าผลิตภัณฑ์ส่วนใหญ่จะมีสีขาวนวลที่ดูคล้ายคลึงกัน แต่โหมดมืดก็มีบางสิ่งที่แตกต่างออกไปซึ่งให้ความรู้สึกลึกลับและแปลกใหม่

นอกจากนี้ยังให้โอกาสที่ดีในการนำเสนอเนื้อหากราฟิก เช่น แดชบอร์ด รูปภาพ และภาพถ่ายในรูปแบบใหม่

โหมดมืดกับแสงของ Twitter
ความงามของโหมดมืดของ Twitter เหนือโหมดแสง (ตัวอย่างขนาดใหญ่)

เมื่อคุณรู้แล้วว่าเหตุใดคุณจึงควรใช้โหมดมืดในเว็บแอปถัดไป มาเจาะลึกเข้าไปในองค์ประกอบที่มีสไตล์ ซึ่งเป็นทรัพยากรที่กำหนดของบทช่วยสอนนี้

โหมดมืดคือชุดสีของอินเทอร์เฟซที่แสดงข้อความและองค์ประกอบอินเทอร์เฟซบนพื้นหลังสีเข้ม ซึ่งทำให้ดูบนโทรศัพท์มือถือ แท็บเล็ต และคอมพิวเตอร์ได้ง่ายขึ้นเล็กน้อย

อะไรคือองค์ประกอบที่มีสไตล์?

ตลอดบทความนี้ เราจะใช้ไลบรารีที่มีสไตล์องค์ประกอบบ่อยมาก มีหลายวิธีในการจัดรูปแบบเว็บแอปที่ทันสมัยอยู่เสมอ มีวิธีการจัดรูปแบบแบบดั้งเดิมในระดับเอกสาร ซึ่งรวมถึงการสร้างไฟล์ index.css และเชื่อมโยงไปยัง HTML หรือการจัดรูปแบบภายในไฟล์ HTML

มีการเปลี่ยนแปลงมากมายในวิธีการจัดรูปแบบเว็บแอปเมื่อเร็วๆ นี้ นับตั้งแต่เปิดตัว CSS-in-JS

CSS-in-JS หมายถึงรูปแบบที่ CSS ประกอบขึ้นโดยใช้ JavaScript ใช้เทมเพลตที่ติดแท็กเพื่อจัดรูปแบบองค์ประกอบในไฟล์ JavaScript

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ CSS-in-JS โปรดดูบทความของ Anna Monus ในหัวข้อนี้

styled-components คือไลบรารี CSS-in-JS ที่ให้คุณใช้ฟีเจอร์ทั้งหมดของ CSS ที่คุณชื่นชอบ รวมถึงคิวรี่สื่อ ตัวเลือกหลอก และการซ้อน

ทำไมต้องเป็นองค์ประกอบที่มีสไตล์?

styled-components ถูกสร้างขึ้นด้วยเหตุผลดังต่อไปนี้:

  • ไม่มีชื่อชั้น นรก
    แทนที่จะต้องเกาหัวเพื่อค้นหาชื่อคลาสสำหรับองค์ประกอบ styled-components จะสร้างชื่อคลาสเฉพาะสำหรับสไตล์ของคุณ คุณจะไม่ต้องกังวลกับการสะกดผิดหรือใช้ชื่อชั้นเรียนที่ไม่มีความหมาย
  • การใช้อุปกรณ์ประกอบฉาก
    styled-components ช่วยให้เราสามารถขยายคุณสมบัติการจัดสไตล์โดยใช้พารามิเตอร์ props ซึ่งมักใช้ใน React ดังนั้นจึงส่งผลต่อความรู้สึกของส่วนประกอบแบบไดนามิกผ่านสถานะของแอปพลิเคชัน
  • รองรับไวยากรณ์ Sass
    การเขียนไวยากรณ์ Sass นอกกรอบโดยไม่ต้องตั้งค่าตัวประมวลผลล่วงหน้าหรือเครื่องมือสร้างเพิ่มเติมสามารถทำได้ด้วยองค์ประกอบที่มีสไตล์ ในการกำหนดสไตล์ของคุณ คุณสามารถใช้อักขระ & เพื่อกำหนดเป้าหมายองค์ประกอบปัจจุบัน ใช้ตัวเลือกหลอก และทดลองกับการซ้อน
  • ธีม
    styled-components มีการสนับสนุนชุดรูปแบบที่สมบูรณ์โดยการส่งออกส่วนประกอบ wrapper ThemeProvider ส่วนประกอบนี้จัดเตรียมธีมให้กับส่วนประกอบ React ทั้งหมดภายในตัวมันเองผ่าน Context API ในแผนผังการแสดงผล องค์ประกอบที่มีสไตล์ทั้งหมดจะมีสิทธิ์เข้าถึงธีมที่จัดเตรียมไว้ แม้ว่าจะอยู่ลึกหลายระดับก็ตาม ในขณะที่เราดำเนินการต่อในบทช่วยสอนนี้ เราจะเจาะลึกถึงคุณสมบัติธีมขององค์ประกอบที่มีสไตล์

หากต้องการเรียนรู้ข้อดีเพิ่มเติมของส่วนประกอบที่มีสไตล์ โปรดดูบทความของ Kris Guzman

การใช้โหมดมืด

ในบทความนี้ เราจะใช้โหมดมืดบนหน้าเว็บที่คล้ายกับ YouTube

เพื่อปฏิบัติตาม ตรวจสอบให้แน่ใจว่าคุณโคลนที่เก็บดั้งเดิมจากสาขา starter

การตั้งค่า

มาติดตั้งการพึ่งพาทั้งหมดในไฟล์ package.json ของเรา จากเทอร์มินัล ให้รันคำสั่งต่อไปนี้:

 npm install

เมื่อติดตั้งสำเร็จ ให้รัน npm start นี่คือลักษณะของหน้าเว็บที่ไม่มีการใช้โหมดมืด

หน้าเว็บที่จะใช้โดยไม่มีโหมดมืด
หน้าเว็บที่จะใช้โดยไม่มีโหมดมืด (ตัวอย่างขนาดใหญ่)

ในการติดตั้ง styled-components ในเทอร์มินัลของคุณให้รัน npm install styled-components

การดำเนินการ

ในการปรับใช้โหมดมืด เราจำเป็นต้องสร้างองค์ประกอบสี่ส่วนที่แตกต่างกัน

  • Theme
    ซึ่งรวมถึงคุณสมบัติสีของธีมสีอ่อนและสีเข้มของเรา
  • GlobalStyles
    ประกอบด้วยสไตล์สากลสำหรับทั้งเอกสาร
  • Toggler
    ซึ่งจะเก็บองค์ประกอบปุ่มที่สลับการทำงาน
  • useDarkMode
    เบ็ดที่กำหนดเองนี้จัดการตรรกะที่อยู่เบื้องหลังการเปลี่ยนธีมและความคงอยู่ของธีมของเราใน localStorage

ส่วนประกอบธีม

ในโฟลเดอร์ src คุณจะเห็นส่วนประกอบในโฟลเดอร์ components สร้างไฟล์ Themes.js และเพิ่มโค้ดต่อไปนี้ลงไป

 export const lightTheme = { body: '#FFF', text: '#363537', toggleBorder: '#FFF', background: '#363537', } export const darkTheme = { body: '#363537', text: '#FAFAFA', toggleBorder: '#6B8096', background: '#999', }

ที่นี่ เราได้กำหนดและส่งออกวัตถุ lightTheme และ darkTheme ด้วยตัวแปรสีที่แตกต่างกัน อย่าลังเลที่จะทดลองและปรับแต่งตัวแปรให้เหมาะกับคุณ

globalStyles Component

ที่เหลืออยู่ในโฟลเดอร์ components ของคุณ สร้างไฟล์ globalStyles.js และเพิ่มรหัสต่อไปนี้:

 import { createGlobalStyle} from "styled-components" export const GlobalStyles = createGlobalStyle` body { background: ${({ theme }) => theme.body}; color: ${({ theme }) => theme.text}; font-family: Tahoma, Helvetica, Arial, Roboto, sans-serif; transition: all 0.50s linear; } `

เราได้นำเข้า createGlobalStyle จากองค์ประกอบที่มีสไตล์ เมธอด createGlobalStyle แทนที่เมธอด injectGlobal ที่เลิกใช้แล้วจาก styled-components เวอร์ชัน 3 เมธอดนี้จะสร้างคอมโพเนนต์ React ซึ่งเมื่อเพิ่มลงในทรีคอมโพเนนต์ของคุณจะใส่สไตล์โกลบอลลงในเอกสาร ในกรณีของเรา App.js

เรากำหนดองค์ประกอบ GlobalStyle และกำหนดคุณสมบัติ background และ color ให้กับค่าจากวัตถุของธีม ดังนั้น ทุกครั้งที่เราสลับการสลับ ค่าจะเปลี่ยนไปขึ้นอยู่กับธีมสีเข้มหรือวัตถุธีมสีอ่อนที่เราส่งไปยัง ThemeProvider (ซึ่งจะถูกสร้างขึ้นในภายหลังเมื่อเราดำเนินการต่อไป)

คุณสมบัติการเปลี่ยนแปลง 0.50s ช่วยให้การเปลี่ยนแปลงนี้เกิดขึ้นได้ราบรื่นขึ้นเล็กน้อย เพื่อที่เมื่อเราสลับไปมา เราจะเห็นการเปลี่ยนแปลงเกิดขึ้น

การสร้างฟังก์ชันการสลับธีม

ในการใช้ฟังก์ชันสลับธีม เราจำเป็นต้องเพิ่มโค้ดเพียงไม่กี่บรรทัด ในไฟล์ App.js ให้เพิ่มโค้ดต่อไปนี้ (โปรดทราบว่าโค้ดที่ไฮไลต์คือสิ่งที่คุณควรเพิ่ม):

 import React, { useState, useEffect } from "react";
import {ThemeProvider} from "styled-components"; import { GlobalStyles } from "./components/Globalstyle"; import { lightTheme, darkTheme } from "./components/Themes"
import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]);
 const [theme, setTheme] = useState('light'); const themeToggler = () => { theme === 'light' ? setTheme('dark') : setTheme('light') }
 useEffect(() => { const timer = setTimeout(() => { setVideos(dummyData); }, 1000); return () => clearTimeout(timer); }, []); return (
 <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}> <> <GlobalStyles/>
 <div className="App">
 <button onClick={themeToggler}>Switch Theme</button>
 { videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div>
 </> </ThemeProvider>
); }; export default App;

โค้ดที่ไฮไลต์คือโค้ดที่เพิ่มใหม่ใน App.js เราได้นำเข้า ThemeProvider จาก styled-components ThemeProvider เป็นองค์ประกอบตัวช่วยในไลบรารีองค์ประกอบที่มีสไตล์ที่ให้การสนับสนุนชุดรูปแบบ องค์ประกอบตัวช่วยนี้จะแทรกธีมลงในองค์ประกอบ React ทั้งหมดด้านล่างผ่าน Context API

ในแผนผังการแสดงผล องค์ประกอบที่มีสไตล์ทั้งหมดจะมีสิทธิ์เข้าถึงธีมที่จัดเตรียมไว้ แม้ว่าจะอยู่ลึกหลายระดับก็ตาม ตรวจสอบส่วน "ชุดรูปแบบ"

ต่อไป เรานำเข้าเสื้อคลุม ./components/Globalstyle จาก ./components/ GlobalStyle สุดท้ายนี้ จากด้านบนสุด เรานำเข้าทั้งวัตถุ lightTheme และ darkTheme จาก ./components/ ./components/Themes

ในการสร้างวิธีการสลับ เราต้องการสถานะที่เก็บค่าสีเริ่มต้นของธีมของเรา ดังนั้นเราจึงสร้างสถานะของ theme และตั้งค่าสถานะเริ่มต้นเป็น light โดยใช้ useState hook

ตอนนี้สำหรับฟังก์ชั่นการสลับ

เมธอด themeToggler ใช้โอเปอเรเตอร์ ternary เพื่อตรวจสอบสถานะของ theme และสลับระหว่างความมืดหรือสว่างตามค่าของเงื่อนไข

ThemeProvider ซึ่งเป็นองค์ประกอบผู้ช่วยที่มีสไตล์ ล้อมทุกอย่างในคำสั่ง return และแทรกส่วนประกอบใดๆ ด้านล่าง โปรดจำไว้ว่า GlobalStyles ของเราใส่ สไตล์สากล ลงในส่วนประกอบของเรา ดังนั้นจึงถูกเรียกภายในองค์ประกอบห่อหุ้ม ThemeProvider

สุดท้ายนี้ เราได้สร้างปุ่มที่มีเหตุการณ์ onClick ซึ่งกำหนดเมธอด themeToggler ของเราให้กับมัน

มาดูผลลัพธ์กันก่อน

โหมดมืดใช้งานโดยไม่มีการคงอยู่
โหมดมืดใช้งานโดยไม่มีการคงอยู่ (ตัวอย่างขนาดใหญ่)

ไฟล์ App.js ของเราต้องมีการ refactored; รหัสจำนวนมากไม่แห้ง (DRY ย่อมาจาก "อย่าพูดซ้ำ" ซึ่งเป็นหลักการพื้นฐานของการพัฒนาซอฟต์แวร์ที่มุ่งลดการทำซ้ำ) ตรรกะทั้งหมดดูเหมือนจะอยู่ใน App.js ; เป็นการดีที่จะแยกตรรกะของเราออกเพื่อความชัดเจน ดังนั้น เราจะสร้างส่วนประกอบที่จัดการฟังก์ชันการสลับ

สลับส่วนประกอบ

ยังอยู่ในโฟลเดอร์ components ให้สร้างไฟล์ Toggler.js และเพิ่มโค้ดต่อไปนี้ลงไป:

 import React from 'react' import { func, string } from 'prop-types'; import styled from "styled-components" const Button = styled.button` background: ${({ theme }) => theme.background}; border: 2px solid ${({ theme }) => theme.toggleBorder}; color: ${({ theme }) => theme.text}; border-radius: 30px; cursor: pointer; font-size:0.8rem; padding: 0.6rem; } \`; const Toggle = ({theme, toggleTheme }) => { return ( <Button onClick={toggleTheme} > Switch Theme </Button> ); }; Toggle.propTypes = { theme: string.isRequired, toggleTheme: func.isRequired, } export default Toggle;

เพื่อให้ทุกอย่างเรียบร้อย เราได้จัดรูปแบบปุ่มสลับของเราในองค์ประกอบ Toggle โดยใช้ฟังก์ชันที่ styled จากองค์ประกอบที่มีสไตล์

นี่เป็นเพียงการนำเสนอเท่านั้น คุณสามารถจัดรูปแบบปุ่มได้ตามที่เห็นสมควร

ภายในองค์ประกอบ Toggle เราส่งอุปกรณ์ประกอบฉากสองชิ้น:

  • theme ให้ชุดรูปแบบปัจจุบัน (สว่างหรือมืด);
  • ฟังก์ชัน toggleTheme จะใช้เพื่อสลับระหว่างธีมต่างๆ

ต่อไป เราจะคืนค่าคอมโพเนนต์ Button และกำหนดฟังก์ชัน toggleTheme ให้กับเหตุการณ์ onClick

สุดท้ายนี้ เราใช้ propTypes เพื่อกำหนดประเภทของเรา ตรวจสอบให้แน่ใจว่า theme ของเราเป็น string และ isRequired ในขณะที่ toggleTheme ของเราเป็น func และ isRequired

การใช้ Custom Hooks ( useDarkMode )

เมื่อสร้างแอปพลิเคชัน ความสามารถในการปรับขนาดเป็นสิ่งสำคัญยิ่ง ซึ่งหมายความว่าตรรกะทางธุรกิจของเราต้องนำมาใช้ใหม่ได้ เพื่อให้เราสามารถใช้งานได้ในหลายๆ ที่และแม้กระทั่งในโครงการต่างๆ

ด้วยเหตุนี้จึงเป็นการดีที่จะย้ายฟังก์ชันการสลับของเราไปยังส่วนประกอบที่แยกจากกัน สำหรับสิ่งนั้น เราจะสร้างเบ็ดที่กำหนดเอง

มาสร้างไฟล์ใหม่ที่ชื่อ useDarkMode.js ในโฟลเดอร์ components และย้ายตรรกะของเราไปที่ไฟล์นี้ด้วยการปรับแต่งบางอย่าง เพิ่มรหัสต่อไปนี้ในไฟล์:

 import { useEffect, useState } from 'react'; export const useDarkMode = () => { const [theme, setTheme] = useState('light'); const setMode = mode => { window.localStorage.setItem('theme', mode) setTheme(mode) }; const themeToggler = () => { theme === 'light' ? setMode('dark') : setMode('light') }; useEffect(() => { const localTheme = window.localStorage.getItem('theme'); localTheme && setTheme(localTheme) }, []); return [theme, themeToggler] };

เราได้เพิ่มบางสิ่งที่นี่

  • setMode
    เราใช้ localStorage เพื่อยืนยันระหว่างเซสชันในเบราว์เซอร์ ดังนั้น หากผู้ใช้เลือกธีมสีเข้มหรือสีอ่อน นั่นคือสิ่งที่พวกเขาจะได้รับเมื่อเข้าชมแอปในครั้งต่อไป หรือหากพวกเขาโหลดหน้าซ้ำ ดังนั้น ฟังก์ชันนี้จะตั้งค่าสถานะของเราและส่ง theme ไปที่ localStorage
  • themeToggler
    ฟังก์ชันนี้ใช้ตัวดำเนินการ ternary เพื่อตรวจสอบสถานะของธีมและสลับความมืดหรือแสงตามความเป็นจริงของเงื่อนไข
  • useEffect
    เราได้ติดตั้ง useEffect hook เพื่อตรวจสอบการติดตั้งส่วนประกอบ หากผู้ใช้ได้เลือกธีมไว้ก่อนหน้านี้ เราจะส่งต่อไปยังฟังก์ชัน setTheme ของเรา ในท้ายที่สุด เราจะคืน theme ซึ่งประกอบด้วย theme ที่เลือกและฟังก์ชัน themeToggler เพื่อสลับไปมาระหว่างโหมดต่างๆ

ฉันคิดว่าคุณจะเห็นด้วยว่าองค์ประกอบโหมดมืดของเราดูโฉบเฉี่ยว

ไปที่ App.js เพื่อดูขั้นตอนสุดท้าย

 import React, { useState, useEffect } from "react"; import {ThemeProvider} from "styled-components";
import {useDarkMode} from "./components/useDarkMode"
import { GlobalStyles } from "./components/Globalstyle"; import { lightTheme, darkTheme } from "./components/Themes" import Toggle from "./components/Toggler" import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]);
 const [theme, themeToggler] = useDarkMode(); const themeMode = theme === 'light' ? lightTheme : darkTheme;
useEffect(() => { const timer = setTimeout(() => { setVideos(dummyData); }, 1000); return () => clearTimeout(timer); }, []); return (
 <ThemeProvider theme={themeMode}>
 <> <GlobalStyles/> <div className="App">
 <Toggle theme={theme} toggleTheme={themeToggler} />
 { videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div> </> </ThemeProvider> ); }; export default App;

โค้ดที่เน้นสีถูกเพิ่มใหม่ไปยัง App.js

ขั้นแรก เรานำเข้า hook แบบกำหนดเองของเรา ทำลายโครงสร้างอุปกรณ์ประกอบฉากของ theme และ themeToggler และตั้งค่าด้วยฟังก์ชัน useDarkMode

โปรดทราบว่าเมธอด useDarkMode จะแทนที่ สถานะ theme ของเรา ซึ่งเดิมอยู่ใน App.js

เราประกาศตัวแปร themeMode ซึ่งแสดงธีมสีอ่อนหรือสีเข้มตามเงื่อนไขของโหมด theme ในขณะนั้น

ตอนนี้ คอมโพเนนต์ wrapper ThemeProvider ของเราได้รับการกำหนดตัวแปร themeMode ที่เพิ่งสร้างขึ้นเมื่อเร็วๆ นี้ให้กับพร็อพ theme

และสุดท้าย แทนที่ปุ่มปกติ เราส่งผ่านองค์ประกอบ Toggle

โปรดจำไว้ว่าในองค์ประกอบ Toggle ของเรา เราได้กำหนดและจัดรูปแบบปุ่ม และส่งทั้ง theme และ toggleTheme ไปเป็นอุปกรณ์ประกอบฉาก ดังนั้น สิ่งที่เราต้องทำคือส่งอุปกรณ์ประกอบฉากเหล่านี้อย่างเหมาะสมไปยังองค์ประกอบ Toggle ซึ่งจะทำหน้าที่เป็นปุ่มของเราใน App.js

ใช่! โหมดมืดของเราได้รับการตั้งค่าและยังคงอยู่โดยไม่เปลี่ยนสีเมื่อรีเฟรชหรือเข้าชมหน้าในแท็บใหม่

ลองดูผลลัพธ์ในการดำเนินการ:

ใช้โหมดมืด แต่มีข้อผิดพลาดในสีของปุ่มเมื่อเบราว์เซอร์โหลดซ้ำ
ใช้โหมดมืด แต่มีข้อผิดพลาดในสีของปุ่มเมื่อเบราว์เซอร์โหลดซ้ำ (ตัวอย่างขนาดใหญ่)

เกือบทุกอย่างทำงานได้ดี แต่มีสิ่งหนึ่งที่เราทำได้เพื่อทำให้ประสบการณ์ของเรายอดเยี่ยม เปลี่ยนเป็นธีมสีเข้มแล้วโหลดหน้าซ้ำ คุณเห็นว่าสีน้ำเงินในปุ่มโหลดก่อนสีเทาในช่วงเวลาสั้น ๆ หรือไม่? ที่เกิดขึ้นเนื่องจากตะขอ useState ของเราเริ่มต้นธีม light ในขั้นต้น หลังจากนั้น useEffect จะทำงาน ตรวจสอบ localStorage จากนั้นตั้งค่า theme เป็น dark ข้ามไปที่ hook ที่กำหนดเองของเรา useDarkMode.js และเพิ่มโค้ดเล็กน้อย:

 import { useEffect, useState } from 'react'; export const useDarkMode = () => { const [theme, setTheme] = useState('light');
 const [mountedComponent, setMountedComponent] = useState(false)
 const setMode = mode => { window.localStorage.setItem('theme', mode) setTheme(mode) }; const themeToggler = () => { theme === 'light' ? setMode('dark') : setMode('light') }; useEffect(() => { const localTheme = window.localStorage.getItem('theme'); localTheme ? setTheme(localTheme) : setMode('light')
 setMountedComponent(true)
 }, []); return [theme, themeToggler, }, []); return [theme, themeToggler, mountedComponent ]
};

โค้ดที่ไฮไลต์เป็นเพียงโค้ดเดียวที่เพิ่มใน useDarkMode.js เราได้สร้างสถานะอื่นชื่อ mountedComponent และตั้งค่าเริ่มต้น false โดยใช้ useState hook ถัดไป ภายใน useEffect hook เราตั้งค่าสถานะ mountedComponent true โดยใช้ setMountedComponent สุดท้าย ในอาร์เรย์ return เรารวมสถานะ mountedComponent

สุดท้าย มาเพิ่มโค้ดเล็กน้อยใน App.js เพื่อให้ทุกอย่างทำงานได้

 import React, { useState, useEffect } from "react"; import {ThemeProvider} from "styled-components"; import {useDarkMode} from "./components/useDarkMode" import { GlobalStyles } from "./components/Globalstyle"; import { lightTheme, darkTheme } from "./components/Themes" import Toggle from "./components/Toggler" import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]);
 const [theme, themeToggler, mountedComponent] = useDarkMode();
 const themeMode = theme === 'light' ? lightTheme : darkTheme; useEffect(() => { const timer = setTimeout(() => { setVideos(dummyData); }, 1000); return () => clearTimeout(timer); }, []);
 if(!mountedComponent) return <div/>
 return ( <ThemeProvider theme={themeMode}> <> <GlobalStyles/> <div className="App"> <Toggle theme={theme} toggleTheme={themeToggler} /> { videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div> </> </ThemeProvider> ); }; export default App;

เราได้เพิ่มสถานะ mountedComponent ของเราเป็นส่วนประกอบในเบ็ด useDarkMode ของเรา และเราได้ตรวจสอบว่าคอมโพเนนต์ของเราได้ติดตั้งแล้วหรือไม่ เพราะนี่คือสิ่งที่เกิดขึ้นในเบ็ด useEffect หากยังไม่เกิดขึ้น เราจะสร้าง div ที่ว่างเปล่า

มาดูผลลัพธ์ของหน้าเว็บโหมดมืดของเรากัน

ผลลัพธ์สุดท้ายของโหมดมืด
ผลลัพธ์สุดท้ายของโหมดมืด (ตัวอย่างขนาดใหญ่)

ตอนนี้ คุณจะสังเกตเห็นว่าในขณะที่อยู่ในโหมดมืด เมื่อหน้าโหลดซ้ำ สีของปุ่มจะไม่เปลี่ยนแปลง

บทสรุป

โหมดมืดกลายเป็นความชอบของผู้ใช้มากขึ้นเรื่อยๆ และการใช้งานในเว็บแอป React นั้นง่ายกว่ามากเมื่อใช้แรปเปอร์ธีม ThemeProvider ในองค์ประกอบที่มีสไตล์ ไปข้างหน้าและทดลองกับองค์ประกอบที่มีสไตล์เมื่อคุณใช้โหมดมืด คุณสามารถเพิ่มไอคอนแทนปุ่มได้

โปรดแชร์ความคิดเห็นและประสบการณ์ของคุณเกี่ยวกับคุณลักษณะการจัดรูปแบบในองค์ประกอบที่มีสไตล์ในส่วนความคิดเห็นด้านล่าง ฉันชอบที่จะเห็นสิ่งที่คุณคิด!

พื้นที่เก็บข้อมูลสนับสนุนสำหรับบทความนี้มีอยู่ใน GitHub นอกจากนี้ ตรวจสอบออกใน CodeSandbox

อ้างอิง

  • “เอกสารประกอบ” ส่วนประกอบที่มีสไตล์
  • “สร้างโหมดมืดของแอปโดยใช้ส่วนประกอบที่มีสไตล์”, Tom Nolan, Medium