How to toggle a Boolean state in React

avatar

Borislav Hadzhiev

Sun Apr 24 20222 min read

banner

Photo by Oleg Ivanov

Toggle a Boolean state in React #

To toggle a boolean state in React:

  1. Use the useState hook to track the state of the boolean.
  2. Pass a function to the setState function the hook returns.
  3. Toggle the boolean based on the current value, e.g. setIsLoading(current => !current).
App.js
import {useState} from 'react'; export default function App() { // 👇️ initialize boolean to false const [isLoading, setIsLoading] = useState(false); const toggleIsLoading = () => { // 👇️ passed function to setState setIsLoading(current => !current); }; return ( <div> <button onClick={toggleIsLoading}>Toggle loading state</button> {isLoading && <h2>Loading...</h2>} </div> ); }

toggle boolean state

We passed a function to setIsLoading because the function is guaranteed to be called with the current (most up to date) value for the isLoading boolean.

In the example, we simply toggle the boolean and return the result to update the state.

We used the logical NOT (!) operator to flip the boolean value.

Here are some examples of using the logical NOT operator.

App.js
console.log(!true); // 👉️ false console.log(!false); // 👉️ true
Note that you shouldn't try to immediately access the boolean state variable after changing it.

If you try to access the isLoading state variable immediately after using the setIsLoading function to update it, there is no guarantee that you'll get the current (most up to date) value.

If you need to listen to state changes, add the state variables to the dependencies array of the useEffect hook.

App.js
import {useEffect, useState} from 'react'; export default function App() { const [isLoading, setIsLoading] = useState(false); const toggleIsLoading = () => { // 👇️ passed function to setState setIsLoading(current => !current); }; useEffect(() => { // 👇️ if you need to listen for changes of isLoading boolean console.log('isLoading is: ', isLoading); }, [isLoading]); return ( <div> <button onClick={toggleIsLoading}>Toggle loading state</button> {isLoading && <h2>Loading...</h2>} </div> ); }

We added the isLoading state variable to the hook's dependencies array, so any time isLoading changes, the logic in our useEffect hook will re-run.

Note that the hook is also invoked when the component mounts.

If you don't want to run the logic in your useEffect hook on the initial render, but only when the specific state variable changes, use a ref to return early on the initial render.

App.js
import {useEffect, useState, useRef} from 'react'; export default function App() { const [isLoading, setIsLoading] = useState(false); const toggleIsLoading = () => { setIsLoading(current => !current); }; const isFirstRender = useRef(true); useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; return; // 👈️ return early if first render } console.log('isLoading is: ', isLoading); }, [isLoading]); return ( <div> <button onClick={toggleIsLoading}>Toggle loading state</button> {isLoading && <h2>Loading...</h2>} </div> ); }

We used a ref to exit early when the useEffect hook is ran on mount.

Use this approach if you want to listen for state changes but need to skip the first render.

Use the search field on my Home Page to filter through my more than 1,000 articles.