Darkmode Using React Context

moon-ico

This is an example app I made using create-react-app to show implementing darkmode using react context with hooks & localStorage.

Features

  • Supports prefers-color-scheme
  • Fades to Black
  • Uses localStorage
  • Uses React Hooks
  • Uses React State
  • Uses React Context

Context

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

📝 Context in React Documentation

Use createContext to initialize react context.

export const ThemeContext = createContext();

Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes.

Wrap the content in App.js inside of the Context.Provider element.

Toggle State

Use useState to toggle the state of darkMode.

const [darkMode, setdarkMode] = useState();

const toggleDark = () => {
  setdarkMode(!darkMode)
}

Initialize On Component Load

Use useEffect to load the main functions for toggling state once the component is loaded.

	useEffect(() => {
		setdarkMode(false)
		const lsDark = JSON.parse(localStorage.getItem('darkMode'))
    if (lsDark) {
      setdarkMode(lsDark)
    }
	}, [])

Store Setting

One of the easiest ways to store a setting is to utilize localStorage using localStorage.setItem & localStorage.getItem.

Supporting Browser Option

Most browsers support prefers-color-scheme option which allows sites to automatically switch to darkmode without user interaction.

This is a boolean value so we just need to check if it equals true.

const prefersDarkMode = () =>
  window.matchMedia('(prefers-color-scheme: dark)').matches === true

Component

Creating a component to toggle darkMode is pretty simple as state is just a bool.

The only thing we need to code in is a check to toggle the moon & sun icons.

const ToggleTheme = () => {
	const { darkMode, toggleDark } = useContext(ThemeContext);

	return (
		<div className="darkmode-container">
			<button className="toggle-darkmode" onClick={toggleDark}>
			{darkMode ? (
				<img src={sun} className="sun-icon" alt="sun-icon" />
			) : (
				<img src={moon} className="moon-icon" alt="moon-icon" />
			)}
			</button>
 		</div>
	)
}

This project can be downloaded from github.

Download