#9 Introduction to Hooks - Delightful React

I Code, Teach and Build Javascript stuff.

We are finally ready to level up our components. Until now, all our components did was show a few elements. It’s time to to create truly powerful components that can hold internal state, run side-effects and do so much more. Ready? Let’s do this!
*Note: This article is a part of the Delightful React Series, as part of which, I am releasing one chapter every day for 25 days. Please support me in anyway you can! *
Theory time
Pure vs Impure functions
Until now, we worked with component instances which didn’t have any internal state. They only displayed the elements contained within them and used props for different behaviour. They didn’t have a state of their own. They are pure.
In functional programming, pure functions are functions which give the same output for the same input.
Pure functions and pure components are very similar. Functions take arguments as input while components take props as input.

On the contrary impure functions may not return the same value for the same inputs. They can have an internal state to them, or they can be referring to global values for computation.

Components are powerful with state
State makes components much more powerful. They allow components to have their own internal memory and handle much more powerful interactions. To create a state variable for a component in modern React, we need to start using hooks.
We need to prepare some UI for the hooks demo first
Let’s modify our blogpost page that currently looks like this.
//pages/blogpost.js
import Heading from '../src/components/Heading'
function Post(){
return <div>
<Heading>
Delightful React
</Heading>
<img
src="https://assets.delightful-react.com/scenery.jpg"
/>
<p>The best way to learn React!</p>
<a href="https://google.com">Google</a>
<br/>
<button>Click Me!</button>
</div>
}
export default Post;
Let’s add a couple of components and use them inside the Post component.
//pages/blogpost.js
import Heading from "../src/components/Heading";
function PostBody() {
return (
<div className="blogpost">
<Heading>Delightful React</Heading>
<img
src="https://assets.delightful-react.com/scenery.jpg"
className="featured-image"
/>
<p className="caption">
Scelerisque consectetur posuere lacinia est parturient elementum ...
</p>
<div className="tags-and-upvote">
<div className="tags">
<a>React</a>
<a>Javascript</a>
<a>Delightful</a>
</div>
<button className="upvote-button">
Click me
</button>
</div>
<p>Ultrices ac bibendum lacinia ...</p>
</div>
);
}
function AddComment() {
return (
<div className="add-comment">
<h2>Submit a comment</h2>
<form>
<div className="input-row">
<input type="text" />
<input type="email" />
</div>
<textarea />
<button>Submit</button>
</form>
</div>
);
}
function Post() {
return (
<div>
<PostBody/>
<button >Add A Comment</button>
<AddComment/>
</div>
);
}
export default Post
We just added a couple of components and split the code. Our blogpost page is a lot more fleshed out now.

Now, let’s use state within our PostBody.
- Let’s start use the “Add Comment” button to show the comment form. Initially the form will be hidden
- When the "Add a Comment" is clicked, we want to show open the form.
To achieve this, we want our component to maintain boolean state variable which represents whether the comment form is visible or not. Initially that state variable is false and when the button is clicked, we want to use an event handler to change the state to true. To create a state variable, we need to talk about React hooks.
React hooks
React hooks super charge React components. Function components in React start off as pure components, but can be made stateful using hooks.

React Hooks are special functions. Hooks are functions which are meant to be used only inside React components and different hooks solve different purposes. Let’s use the useState hook that creates a state variable inside a component like so.
useState and it’s usage.
To create a state variable we need to do import the useState hook from React.
import {useState} from 'react'
The useState hook function takes the initial value of the state variable as argument. It returns an array of 2 items. The first item in the array is the state variable value itself. The second item in the array is a function which can be used to update the state variable and make the component update and rerender.
function MyComponent(){
const stateInfoArray = useState(5)
const value = stateInfoArray[0] //5
const setValue = stateInfoArray[1] // function
...
}
We used a variable called stateInfo which will be the array that useState returns. We then grabbed value and setState from the array. If we use useState like this, then value, the state variable, is initialised to 5 and it can later be changed in the component using setValue. A shorter syntax to do the same thing would be to use array destructuring.
function MyComponent(){
const [value,setValue] = useState(5)
...
}
Now, let’s use this inside our Post component like so.
function Post() {
const [showCommentUI, setShowCommentUI] = useState(false)
return (
<div>
<PostBody/>
<button >Add A Comment</button>
{showCommentUI ? <AddComment/> : null}
</div>
);
}
This will create a state variable named showCommentUI whose value is false.
When used this as a conditional ternary operator expression, the AddComment won’t be visible anymore. It will only show up if showCommentUI’s value is true.
Updating state
The useState hook returns an array of 2 values. The state variable and also a function to update the state variable. This function simply needs to be called with the new value that the state variable needs to be updated to. Calling this function will update the state variable and it triggers a rerender in the component instance. Let’s tie that with the button’s onClick event handler and use it like so.
<button onClick={function(){
setShowCommentUI(true)
}}>Add A Comment</button>
This is how our Post component should now look like.
function Post() {
const [showCommentUI, setShowCommentUI] = useState(false)
return (
<div>
<PostBody/>
<button >Add A Comment</button>
{showCommentUI ? <AddComment/> : null}
</div>
);
}
Try clicking on the button now. We should have our comment form appear after we click on.
State change will automatically cause React to update
Updating state, will cause the React component to immediately rerender. This allows the component to reflect the updated state values into the DOM elements immediately. This ensures that our components are always upto date with the latest changes in the React component.

Each time we update our state variables, React will rerender the component and flush updates to the DOM immediately. Let’s take our Post component a step further. We can make our button toggle the value from false to true and then back from true to false like so.
<button onClick={function(){
if(showCommentUI){
setShowCommentUI(false)
}else{
showCommentUI(true)
}
}}>
{showCommentUI ? "Hide Comment Form" : "Add A Comment" }
</button>
An even shorter version of this will look like this. We can simply negate the existing value of the state variable and call setShowCommentUI with the negated value.
function Post() {
const [showCommentUI, setShowCommentUI] = useState(false)
return (
<div>
<PostBody/>
<button onClick={function(){
setShowCommentUI(!showCommentUI)
}}>{showCommentUI ? "Hide Comment Form" : "Add A Comment" }</button>
{showCommentUI ? <AddComment/> : null}
</div>
);
}
Nice! Isn’t it?
States, components and component instances
Components are function definitions and hooks are declared inside components. But each time we render a component as a new instance, they all have their own separate internal state.

For eg, imagine a React component that renders a button and tracks number of times a button was clicked in a state variable.
function Counter(){
const [counter, setCounter] = useState(0)
return <button onClick={function(){
setCounter(counter+1)
}}>{counter}</button>
}
If we render two instances of this component and click the first button 5 times and the second button 2 times, their internal state counters are updated to 5 and 2 respectively independent of each other.
<Counter/>
<Counter/>
In other words, we created a Counter component and created 2 component instances of it and each of these 2 instances have their own independent state.

Multiple hooks in the same component
A component have any number of hooks.

Let’s move the counter logic into our Post component as an example.
function Post() {
const [showCommentUI, setShowCommentUI] = useState(false);
const [counter, setCounter] = useState(0);
return (
<div>
<PostBody />
<button
onClick={function () {
setShowCommentUI(!showCommentUI);
}}
>
{showCommentUI ? "Hide Comment Form" : "Add A Comment"}
</button>
{showCommentUI ? <AddComment /> : null}
<br />
<button
onClick={function () {
setCounter(counter + 1);
}}
>
{counter}
</button>
<br />
</div>
);
}
Both state variables can be used and updated in the same component instance.
Our components can have any number of hooks within them and they are all managed independently for each instance of the component. This means that all our component instances to have their own little memory inside React and can function independent of one another.
Hooks are just functions?
Hooks are functions. However, they only should be used inside components. There are also some rules that you need to follow when you use hooks. For eg,
- hooks should not be used inside an if-else condition,
- hooks should not be used anywhere else except at the top level of the component ie., not inside a callback that will execute on a button click etc.
These rules are peculiar but are very important. To understand these rules and why they are even needed, we need to understand the internals of a React component instance a bit more.
Keep it going!
We have just started talking about hooks. There is still some way to go. Next, let's talk about the internal of hooks and the rules governing hooks. See you in the next chapter!
Thanks and Please support my work
Writing blog posts and making videos is an effort that takes many hours in my day. I do it because I love teaching and make great content. However, I need your support too. Please support my work and follow my social accounts to help me continue to make great content. Here are my social links.
Follow me on Twiter
Subscribe to my channel on Youtube
Thank you!




