Simple examples of React Hooks usage
React Hooks were introduced in React version 16.8. Hooks are functions that let you “hook into” the React state and lifecycle features straight from function components. There are many benefits of using react hooks. With help of React Hooks we can use React without classes. It allows us to write more readable, cleaner code with less lines of code.
useState
Let’s look at the simplest class component example with some state:
import React from 'react';
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.handleButtonClick = this.handleButtonClick.bind(this);
}
handleButtonClick() {
this.setState({ count: this.state.count + 1 })
}
render() {
return (
<button onClick={this.handleButtonClick}>
{`click: ${this.state.count}`}
</button>
);
}
}
We are keeping the count
value in component state
. Now the same example using functional components with useState
hook. It looks much better:
import React, { useState } from 'react';
function Counter(props) {
const [count, updateCount] = useState(0);
function handleButtonClick() {
updateCount(count + 1);
}
return (
<button onClick={handleButtonClick}>
{`click: ${count}`}
</button>
);
}
The benefits of using functional components are visible at first glance. Less code is required. We do not need to initialize the constructor or bind functions. In this example we are using the useState
hook to keep the component state:
const [count, updateCount] = useState(0);
With this hook we made the count
a stateful variable. The second returned value is a function to update it: updateCount
. We use it each time we will update the count
variable: updateCount(newCountValue)
. Each update will cause re-render of the component. The hook is called with attribute 0
- this is the initial value. Additionally we do not need to call this.state.count
, we simply use count
.
useEffect
The useEffect
hook is the second of the three main React Hooks. It is used to run additional code after render. We can see it as combination of React Component lifecycle methods: componentDidMount
, componentDidUpdate
, and componentWillUnmount
. We can use it for example to add listeners after the component has rendered.
If needed the effect can return a function which is a cleanup function. It is used to perform cleanups e.g. to prevent introduction of memory leaks. It this example we are removing the event listener in the returned cleanup function.
import React, { useEffect } from 'react';
function Position(props) {
function handleMouseMove(e) {
console.log(e.clientX, e.clientY);
}
useEffect(() => {
window.addEventListener("mousemove", handleMouseMove);
return (() => {
window.removeEventListener("mousemove", handleMouseMove);
});
}, []);
return (<div/>);
}
By default the useEffect
hook runs after every render. Sometimes it is not needed to run the ‘effect’ on every change. For example if we want to perform the effect only on certain values change. We can do so by passing an array as an optional second argument to useEffect
. In this case the effect will be run after count
update only:
useEffect(() => {
console.log(count);
}, [count]);
In previous example we passed an empty array []
. This causes to run the hook to run only on component mount (and cleanup on unmount), which is what we wanted there.
The main benefits of using useEffect
hook is encapsulating side effects.
useContext
Last of the three main React Hooks is useContext
. It is used to share data across components. It allows us to create a global state that can be used even in deeply nested components without the need to pass local data around. Let’s see how can we use it. First we create context:
const ThemeContext = React.createContext();
As next we create a provider wrapper. The Provider
accepts a value
prop which is used to pass the context. In our example it’s the theme
variable and handleThemeChange
function. We will have access to them through the useContext
hook.
const ThemeContext = React.createContext();
function ThemeWrapper({ children }) {
const [theme, changeTheme] = useState("dark");
function handleThemeChange(theme) {
changeTheme(theme);
}
const context = {
theme,
handleThemeChange
};
return (
<ThemeContext.Provider value={context}>
{children}
</ThemeContext.Provider>
);
}
Now we wrap the content with our provider:
function App(props) {
return (
<ThemeWrapper>
<Content />
</ThemeWrapper>
);
}
Finally we can connect to the context using the useContext
hook:
import React, { useContext } from "react";
function Content(props) {
const { theme } = useContext(ThemeContext);
return (<div className={theme}>...</div>);
};
We have an easy access to our context. The context is provided to each component in the component tree and will re-render whenever the Provider’s value
prop changes. Using useContext
hook we do not need to pass the props all the tree down.
Want more?
- Subscribe to our mailing list to keep receiving free React lessons.
- Buy our React.js by example book which is full of examples