React Hooks

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.

Before React 16.8, the only way of creating a stateful component was to create a Class-Style component which can provide a component state via state and setState members of the Component class.

useState Hook

The first hook we learned about was the useState hook in the article about Component State.

const myComponent = () => {
const [counter, setCounter] = useState(0);
return (
<>
<div></div>
<button onClick={() => setCounter(counter => counter + 1)}> Increase</button>
</>
);
};

Benefits of React Hooks

useEffect hook

The useEffect hook lets you execute side-effects on components and run operations whenever a component is mounted, unmounted or a dependant value has changed. This can be used for data fetching.

const MyComponent = () => {
const [data, setData] = useState(null);

useEffect(() => {
// will be executed when the component mounts
const controller = new AbortController();
const { signal } = controller();
fetch("https://yesno.wtf/api", { signal })
.then(res => res.json())
.then(data => {
const { answer, image } = data;
setData({answer, image});
});

// When returning a function, it will be executed when the component unmounts
return () => {
// prevent setting of state after component has been destroyed.
controller.abort();
}
}, []);

return (data ?
<>
<img src={data.image} alt={`The answer is ${data.answer}`}>
</> :
<>
<div>Loading</div>
</>
);
};

useMemo hook

The useMemo hook helps you to memoize a value within a component.

Expensive operations like filtering a big array can have a big impact on performance. With useMemo you can ensure the value is only recalculated when necessary:

Example:

// a huge array of Pokemons:
const pokemons = [
'Bulbasaur',
'Ivysaur',
'Venusaur',
'Charmander',
'Charmeleon',
'Charizard',
'Squirtle',
'Wartortle',
'Blastoise',
'Caterpie',
];

const MyComponent = () => {
const [filter, setFilter] = useState('');
const filteredPokemons = useMemo(
() => pokemons.filter(it => it.toLowerCase().startsWith(filter.toLowerCase())),
[pokemons, filter] // dependency array.
);

// .filter is a potentially expensive operation when
// the amount of data is bigger than in this example.
// the filteredPokemons is recalculated every time one
// of the dependencies change

return (
<>
<input value={filter} onChange={(e) => setFilter(e.target.value)} />
<ul>
{filteredPokemons.map(pokemon => (<li key={pokemon}>{pokemon}</li>))}
</ul>
</>
);
};

useContext hook

The useContext api helps you to share state across components using the Context API. The context API is described within its own article: Context API.