To toggle a boolean state in React:
- Use the
useState
hook create the boolean state (if you haven’t already). - Pass a callback to the state updater function (
setState
). - Return the negation of the boolean variable from the callback.
For example:
import { useState } from 'react';
export default function App() {
const [visible, setVisible] = useState(false);
const handleToggle = () => {
setVisible((current) => !current);
};
return (
<div>
<button onClick={handleToggle}>Show name</button>
{visible && <p>Coding Beauty</p>}
</div>
);
}
We create the boolean state with the useState
hook. useState
returns an array of two values, the first is the value of the state, the second is a function that updates the state when it is called.
We pass a callback function to setVisible
because the callback is always passed the latest visible
state.
Tip: Always pass a function to setState
when the new state is computed from the current state data.
In our case, the callback simply negates the boolean value and returns the result to negate the state.
The logical NOT (!) operator converts a truthy value to false
and a falsy value to true
.
console.log(!true); // false
console.log(!false); // true
console.log(!5); // false
console.log(!undefined); // true
Note: In JavaScript there are only 6 falsy values: undefined
, null
, ''
(empty string), NaN
, 0
, and false
. Every other value is truthy and will result in false
when negated.
Perform action on boolean state toggle
Sometimes you want to perform an action outside of re-rendering when the boolean state changes in the component, e.g., a network request. To carry out such an action, place the code in the useEffect
hook and include the boolean state variable in useEffect
‘s dependencies array.
import { useEffect, useState } from 'react';
import axios from 'axios';
export default function App() {
const [visible, setVisible] = useState(false);
const handleToggle = () => {
setVisible((current) => !current);
};
useEffect(() => {
if (visible) {
axios.post('https://example.com/stats/name/views').then(() => {
console.log('Updated stats successfully.')
});
}
}, [visible]);
return (
<div>
<button onClick={handleToggle}>Show name</button>
{visible && <p style={{ color: 'blue' }}>Coding Beauty</p>}
</div>
);
}
The code in the useEffect
hook runs after the component mounts or updates from a change in the visible
state. Here, the state controls the visibility of an element, so in the hook, we check if the element is visible, and if so, we make a network request to a server to update view stats associated with the element.
Perform action on boolean state change but skip first render
Depending on your scenario, you might want the action to run when the component updates from a state change, but not it when it first mounts.
We can do this by creating a ref flag variable having an initial value of false
in the first render, and change its value to true
for all subsequent renders.
import { useEffect, useRef, useState } from 'react';
import axios from 'axios';
export default function App() {
const afterFirstRender = useRef(false);
const [visible, setVisible] = useState(false);
const handleToggle = () => {
setVisible((current) => !current);
};
useEffect(() => {
if (!afterFirstRender.current) {
afterFirstRender.current = true;
return;
}
if (visible) {
axios.post('https://example.com/stats/name/show').then(() => {
console.log('Stats updated successfully')
});
}
}, [visible]);
return (
<div>
<button onClick={handleToggle}>Show name</button>
{visible && <p style={{ color: 'blue' }}>Coding Beauty</p>}
</div>
);
}
useRef
returns a mutable ref object that doesn’t change value when a component is updated. Also, modifying the value of this object’s current
property does not cause a re-render. This is in contrast to the setState
update function returned from useState
.
If the ref’s value is false
, we prevent the action from happening in useEffect
and change the value to true
for the following renders. Otherwise, we execute the action.
Every Crazy Thing JavaScript Does
A captivating guide to the subtle caveats and lesser-known parts of JavaScript.