moon-ico

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

Features #

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