In these series of articles I'm going to answer following questions:
- What are React hooks?
- Why there are React hooks?
- How to use React hooks?
From now on I assume that:
- You have no knowledge of React hooks.
- You have at least basic knowledge of React (any tutorial longer than 5 mins will be enough).
My story
I've been working with React for over two years now. I must admit it's been very nice two years. So I was very sceptical when I heard about React hooks for the first time. "Why change something that is good and works?" When I saw first hooks examples my feeling "this is not a good direction" was even stronger. But hooks kept attacking me from every direction and more and more people seemed to be delighted with the new React addition. I decided to give them a try... and I joined a circle of delighted. But first things first.
What are React Hooks?
Hooks were introduced to React to replace class creation of components. Replace with what? Replace with function creation.
'Whoa!' one can shout. We could have created components with functions this whole time. What the whole fuss with hooks is about? Before I answer this question let us take two steps back.
How do we create components in React?
As a general rule there are two ways to crate components in React.
- Using classes (class components).
- Using functions (function components).
Function components seem to be much easier:
- One doesn't have to "wrestle" with
this
keyword and remember to bind methods. - They are more readable and faster to write.
- They are easier to test and reasoning about.
So let us ask a simple question...
Why there are two ways for creating components in React?
If function components are so "cool" why not using only them? Why would one use classes in the first place?
Class components have two important features not available for function components:
- They can have state.
- They give access to component's lifecycle methods.
What is state? It's the component's ability to "remember" any information about itself.
E.g. a button component can remember whether user clicked it or not. And depending on that render itself in green or red.
What are component's lifecycle methods? Component's lifecycle is a period starting with the first painting of a component in a browser (and even one moment before) up until removing it from there. Lifecycle methods let us execute any code in key moments of component's existance.
E.g. let’s say we'd like to know the height of the button. This information is available after the button is actually rendered in the browser.Thanks to componentDidMount
we can have access to the button and get its height when it's rendered.
We couldn’t have used these features while using function components in the past. But since React 16.8 - thanks to introduction of React hooks - both state and lifecycle methods are available to function components!
Show me some code!
Let's begin our adventure with React hooks from writing a class component.
We have a simple component that renders input field. The user can enter their name and it'll be saved in component state and displayed above the input field.
import React from 'react';
class MyComponent extends React.Component {
state = {
userName: "Bob",
}
handleUserNameChanged = (e) => {
this.setState({ userName: e.target.value });
}
render() {
return(
<>
<h2>User name: {this.state.userName}</h2>
<input
type="text"
value={this.state.userName}
onChange={this.handleUserNameChanged}
/>
</>
);
}
}
Let's write a function component now. The goal is to write a component that has exactly the same functionality as the class component. Let's start with an empty arrow function:
import React from 'react';
const MyComponent = () => {
// code goes here
};
And then do the following:
- Copy the code returned by
render
method. It'll be returned directly by our function component. - Copy
handleUserNameChanged
method and addconst
keyword in front of it. - We don't have
this
keyword in function component. Delete all its occurrences. - We are interested in
userName
notstate.userName
. Remove allstate.
from the code. - We don't define
state
as an object. We defineuserName
variable instead and give it a string"Bob"
as initial value. - Change
setState
with a more descriptive function:setUserName
. We pass it a value we get from input field. This function will be responsible for changing the value we keep in theuserName
variable.
Our function component should look as follows:
import React from 'react';
const MyComponent = () => {
const userName = "Bob";
const handleUserNameChanged = (e) => {
setUserName(e.target.value);
}
return(
<>
<h2>User name: {userName}</h2>
<input
type="text"
value={userName}
onChange={handleUserNameChanged}
/>
</>
);
}
At this stage our component is not working. We get information about an error: setUserName
is not defined. Let's remind ourselves what setUserName
should be? It should be a function that changes the value of the userName
.
We're going to write a naive implementation of that function. This function will accept a new userName
value and (for now) it'll return current userName
value.
const setUserName = (newUserName) => userName;
Now add it to our function component (in line 4):
import React from 'react';
const MyComponent = () => {
const userName = "Bob", setUserName = (value) => userName;
const handleUserNameChanged = (e) => {
setUserName(e.target.value);
}
return(
<>
<h2>User name: {userName}</h2>
<input
type="text"
value={userName}
onChange={handleUserNameChanged}
/>
</>
);
}
Our code almost works. Almost because it shows input field and user name as "Bob". But we can't change that user name. Why? We are lacking the component’s state in which we could keep our new user name. We'd like to use state here. Luckily for us React gives us a useState
hook.
useState hook
useState
is a hook that let us use state in a function component.
useState
hook is a function that returns array with two elements:
- First element is a variable to store a value of our state.
- Second element is a function we can use to change the state with a new value.
We can pass useState
an argument with initial state value. It can be any string
, number
, boolean
, array
or object
. In our example we pass string
"Bob".
We can write:
const state = useState("Bob"); // state is an array
const userName = state[0]; // first element is a state's value
const setUserName = state[1]; // second element is a function
Thanks to array destructuring we can write it more elegant:
const [userName, setUserName] = useState("Bob");
We can read this as follows:
- We want to use state and keep its value in a variable called
userName
. - We can change the state by calling
setUserName
function with a new value. - We set initial
userName
value to"Bob"
.
With this knowledge at hand let's get back to our example. Import useState
from React and use it in the component.
import React, { useState } from 'react'; // import useState hook
const MyComponent = () => {
const [userName, setUserName] = useState("Bob");
const handleUserNameChanged = (e) => {
setUserName(e.target.value);
}
return(
<>
<h2>User name: {userName}</h2>
<input
type="text"
value={userName}
onChange={handleUserNameChanged}
/>
</>
);
}
Now our function component should work exactly the same as our class component. Thanks to React’s useState
hook we've created a function component that can have state!
Great, it's working but where are those miracles?
You may be thinking that adding Hooks to React doesn't bring any spectacular benefits to the table. And actually you're right. If you compare initial class component with its function counterpart there are not too many differences. It's really hard to understand why so many people is so excited about hooks.
I promise you one thing. If you stay with me to the end of this series you'll have a Wow! This is so super! moment. At least I had one.
See you in the next part of the Gentle Introduction to React Hooks!
Thanks for reading! If you liked this let me know! Leave a comment, give a ❤️ or share it!
Feel free to check my Twitter account with more content like this.
Top comments (9)
This was a smooth intro to React hooks, i was very reluctant to read on hooks as i'm a newbie and there's lots of stuff we have to absorb.
I'm now looking for a similar intro to React ContextAPI, i'd appreciate a link from anyone who've come a cross an intro to Context which is done in this similar style 😎
Great work Przemek 😄 transforming a class component into a functional one is always a great way to teach hooks ! I did something similar a while back: dev.to/christopherkade/introductio..., glad to see it's a commonly used method.
Thank you! I felt it was a natural way for someone who worked with React before hooks. BTW I'm gonna check your post :)
Amazing content. Congrats dude :)
Thanks! I hope you'll enjoy the whole series ;)
Nice read, thanks
Thank you. I'm glad you like it!
Great content, waiting for the next one :)
Thank you! Next part almost ready. Stay tuned!