After an awesome response to my previous article Hooks in React, as promised I am back with the second article in my React Series of articles. You can check it out at here. In the previous article, we discussed what are hooks, and how they work. Whereas, this article would focus on some live examples and discussions about some basic hooks of React.
Since their introduction in React, Hooks have served some great purposes. First, let's discuss what are the advantages of hooks.
Advantages of Hooks in React
- Easier to test and work with
- They avoid juggling HOCs, render props, children as functions, and classes
- Code is more readable with Hooks and also has Separate (and isolated) concerns
- Better code modification - Since Hooks are functions, the modification of code is better as modification of functions in JavaScripts is much better than classes
- Hooks also avoid duplicate logic between lifecycle method and components
The above-shared advantages are just some handpicked out of countless of them. Now let's jump on the main part of this discussion, i.e. Basic Hooks in React.
Generally, Hooks in React can be categorized in several built-in Hooks, including 03 Basic and 07 Additional Hooks. Here, we would be discussing the basic Hooks of React.
Basic Hooks in React
There are three (03) basic Hooks to be used while working in React. They are:
- useState
- useEffect
- useContext
useState()
useState Hooks, or Hooks State is the new way of declaring a state in React app. Hook uses useState() functional component for setting and retrieving state. During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState). It can be declared as
const [state, setState] = useState(initialState);
The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component. User/Developer can use setState function as:
setState(newState);
Prerequisite
You MUST import useState from React before using the setState function. You can do so by:
import React, { useState } from 'react';
Let's understand Hook State with the following example:
import React, { useState } from 'react';
function CountApp() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default CountApp;
In the above example, useState is the Hook which needs to call inside a function component to add some local state to it. The useState returns a pair where the first element is the current state value/initial value, and the second one is a function that allows us to update it. Then, we will call this function from an event handler or somewhere else. The useState is similar to this.setState in class. The equivalent code without Hooks looks like as below:
import React, { useState } from 'react';
class CountApp extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p><b>You clicked {this.state.count} times</b></p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
export default CountApp;
useEffect()
After State Hooks, the most basic hook in Reac is the Effect Hook. It allows us to perform side effects (in action) in the functional components. It does not use components lifecycle methods that are available in class components. Before the introduction of Hooks, it was similar to using componentDidMount(), componentDidUpdate(), componentWillUnmount()
lifecycle methods. useEffects() allows web developers to make their web application perform some actions, seamlessly. Such as:
- Updating the DOM
- Fetching and consuming data from a server API
- Setting up a subscription, etc. In other words, useEffect accepts a function that is used to cause an effect in the function.
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
Note: The second parameter can be passed as an empty array if you want the function to run only once
Now, let's see an elongated and useful block of code to further understand the usage of useEffect(). But before that, just like useState, we have to import useEffect from React. For example:
import React, { useState, useEffect } from 'react';
Now, let's understand Hook Effect with the following example:
import React, { useState, useEffect } from 'react';
function CounterExample() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default CounterExample;
The above-coded example is carried forward version of the previous example of useState() with a new feature, which sets the document title to a custom message, including the number of clicks.
There are two types of effect hooks in React, namely:
- Effects without Cleanup
- Effects with Cleanup We will discuss these in our next article.
useContext()
useContext accepts a context object i.e. the value returned from React.createContext and returns the current context value for that context. A component calling useContext will always re-render when the context value changes.
In other words, useContext() hook is used to create common data that can be accessed throughout the component hierarchy without passing the props down manually to each level. Context defined will be available to all the child components without involving βpropsβ.
Before jumping over the example for useContext, let's take a look at an example code, without using useContext, i.e. with the Consumer component (the hard way):
import React from "react";
import ReactDOM from "react-dom";
// Create a Context
const NumberContext = React.createContext();
// It returns an object with 2 values:
// { Provider, Consumer }
function App() {
// Use the Provider to make a value available to all
// children and grandchildren
return (
<NumberContext.Provider value={42}>
<div>
<Display />
</div>
</NumberContext.Provider>
);
}
function Display() {
// Use the Consumer to grab the value from context
// Notice this component didn't get any props!
return (
<NumberContext.Consumer>
{value => <div>The answer is {value}.</div>}
</NumberContext.Consumer>
);
}
ReactDOM.render(<App />, document.querySelector("#root"));
Let's understand what just happened.
First, we create a new context, which we store in NumberContext. This is an object with 2 properties: Provider and Consumer. Theyβre a matched pair, and theyβre born knowing how to communicate with each other (but not with other contexts).
Then, we render the NumberContext.Provider with some contents, and pass a value prop to it. It will make this value available to all of its descendants, and their descendants. The whole subtree will be able to use the Consumer (or useContext) to read out the value.
Finally, we read the value with the Consumer inside the Display component.
useContext() code example
useContext() let's you "USE" context without a Consumer. Letβs rewrite the Display component with the useContext hook:
// import useContext (or we could write React.useContext)
import React, { useContext } from 'react';
// ...
function Display() {
const value = useContext(NumberContext);
return <div>The answer is {value}.</div>;
}
Call useContext(), pass in the context object you got from React.createContext, and out pops the value. Wasn't it easy? But the only thing to watch out for is that you have to pass the whole context object to useContext β not just the Consumer! (this is why I didnβt destructure the Context object right away) The best thing about React is, it will warn you if you forget.
So that was all for today's article. In my previous article, I forgot to mention my mentors, who taught me React. They are Tahir Masood & Zohaad Afzal.
In the next article, we would be covering the types of useEffect() and would try to further dive into the awesome and super cool world of React.
Top comments (3)
It'd be nice if you included some info on useRef too, as it can be used for more than just storing dom elements. I typically use useRef when i need to retain values that should absolutely never impact renders. This helps when you need to reference a value during actions in a component or deal with application layer objects that are just under the surface.
Yeah, it is. But since this article was all about the basic hooks in react, so I tried to keep it as simple as possible.
In the very first code example you write
const [state, initialState] = useState(initialState);
I think you meant
const [state, setState] = useState(initialState);