React day 4/40
Exploring React Hooks: Building a Counter Application
In this project, I embarked on building a simple counter application to explore React's powerful hooks. Using the useState
hook, I learned how to manage state effectively and create a dynamic user interface that responds to user interactions. This hands-on experience solidified my understanding of state management in React and set the stage for more complex projects.
Creating a project
I started by setting up a project using Vite and created a simple component in App.jsx
with a heading and two counter buttons. As a beginner in React, one of the first things I noticed was how Vite automatically applies some basic CSS styles. For example, the buttons were centered, and they had hover effects without me having to write any additional styles.
function App() {
let counter = 5
return (
<>
<h1>Aaks React</h1>
<h2>Counter Value: {counter} </h2>
<button
onClick={addValue}
>Increament value</button>
<br /> <br />
<button>Decreament value</button>
</>
)
}
In this code, I used {}
to inject the counter
variable inside the JSX, which was a part of yesterday’s learning.
Also, when defining the onClick
event handler for the button, I learned that you should use onClick={addValue}
instead of onClick={addValue()}
. The reason is that addValue()
would immediately execute when the component renders, whereas we want it to execute only when the button is clicked. So far, I’m applying the basic JavaScript concepts I’ve learned, which feels great.
Understanding the need for hooks
While working on a simple counter app in React, I initially encountered a problem with updating the UI:
function App() {
let counter = 5
const addValue = () => {
console.log("clicked", counter)
counter += 1
}
return (
<>
<h1>Aaks React</h1>
<h2>Counter Value: {counter} </h2>
<button
onClick={addValue}
>Increament value</button>
<br /> <br />
<button>Decreament value</button>
</>
)
}
Although the counter
value was increasing correctly in the console when I clicked the button, the displayed value on the UI wasn’t updating.
This led me to a key realization: React doesn't automatically update the UI when a variable changes.
The problem is occurring in UI updates. React responds to variable changes, which is where its name comes from—if a variable is changed in one place, React reacts and updates it everywhere it’s used. React’s state management is what allows the UI to respond to changes automatically.
However, unlike in JavaScript, where we manually control UI updates with references, in React, the UI update is not controlled by us. React manages the updates. To handle this, React provides special methods called hooks, and it's through these hooks that data is updated within the component
Introduction to useState
React provides special methods called hooks to manage state changes in functional components. The useState
hook is crucial for managing state inside a component. It allows the UI to update whenever the state changes, which was exactly what I needed.useState
is imported from React import {useState} from ‘react’
and is responsible not just for changing the state but for propagating those changes within the UI and DOM. It ensures that when the state is updated, the UI reflects the change accordingly.
The way to use useState()
is simple. It returns two values in an array format:
let [counter, setCounter] = useState(15);
The 0th index contains the current value (in this case,
counter
), which is the state variable.The 1st index is a function (
setCounter
) that updates this value.
While naming setCounter
isn't strictly required, it’s a common convention to name it setSomething
because it clearly indicates that this function is responsible for controlling the variable (counter
in this case).
Whenever we call setCounter(counter + 1)
, React knows to update the counter
value across the UI wherever it’s used.
Instead of directly modifying counter
using counter = counter + 1
, we use setCounter(counter + 1)
to ensure that the UI updates correctly.
counter = counter + 1 //incorrect
setCounter(counter + 1) //correct
Alternatively, you can also write it like this:
counter = counter + 1;
setCounter(counter);
Both ways will update the state and reflect the change in the UI
Final code
import { useState } from 'react'
import './App.css'
function App() {
let [counter, setCounter] = useState(15)
// let counter = 5
const addValue = () => {
if(counter<20){
counter += 1
setCounter(counter)
}
}
const removeValue = () => {
if(counter>0){
console.log("clicked", counter)
counter -= 1
setCounter(counter)
}
}
return (
<>
<h1>Aaks React</h1>
<h2>Counter Value: {counter} </h2>
<button
onClick={addValue}
>Increament value {counter}</button>
<br /> <br />
<button
onClick={removeValue}
>Decreament value {counter}</button>
</>
)
}
export default App
With this, I was able to build a simple project with two buttons: one to increment the value and another to decrement it, and the result is displayed dynamically using the useState()
hook.
To make it more interesting, I added a limit where the value can’t go below 0 or above 20. This allowed me to experiment with React further, and I’m starting to feel much more familiar and comfortable using it. It was a fun way to solidify my understanding of state management in React!
Subscribe to my newsletter
Read articles from Aaks directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by