React States, Passing Data and Lists, Event Handling
React States
In React, state is a built-in object that allows components to create and manage their own data. State is used to keep track of information that can change over time and influence what is rendered on the screen.
Using State
The useState
hook is used to manage state. The useState
hook returns an array with two elements: the current state value and a function to update it.
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
}
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
State Characteristics
Initialization:
- State can be initialized with a default value as an argument to
useState
.
- State can be initialized with a default value as an argument to
Updating State:
State updates are asynchronous, and React may batch multiple
setState
calls for performance reasons.The state should not be directly mutated. Always use
setState
(class components) or the state updater function (functional components) to update the state.
Conditional Rendering:
- The state can be used to conditionally render parts of the UI.
function App() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const toggleLogin = () => {
setIsLoggedIn(!isLoggedIn);
}
return (
<div>
{isLoggedIn ? <p>Welcome back!</p> : <p>Please log in.</p>}
<button onClick={toggleLogin}>
{isLoggedIn ? 'Log out' : 'Log in'}
</button>
</div>
);
}
- By default the value is set to
false
, hence it will display asPlease log in.
and after clicking it, it will sayWelcome back
on the page.
Handling Multiple State Variables
You can use multiple useState
hooks to manage different state variables in a functional component.
function App() {
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const handleNameChange = (event) => setName(event.target.value);
const handleAgeChange = (event) => setAge(Number(event.target.value));
return (
<div>
<input type="text" value={name} onChange={handleNameChange} placeholder="Name" />
<input type="number" value={age} onChange={handleAgeChange} placeholder="Age" />
<p>Name: {name}, Age: {age}</p>
</div>
);
}
Using State with Objects
If your state is an object, updating it requires spreading the previous state to ensure all properties are preserved.
function App() {
const [user, setUser] = useState({ name: "", age: 0 });
const handleNameChange = (event) => setUser({ ...user, name: event.target.value });
const handleAgeChange = (event) => setUser({ ...user, age: Number(event.target.value) });
return (
<div>
<input type="text" value={user.name} onChange={handleNameChange} placeholder="Name" />
<input type="number" value={user.age} onChange={handleAgeChange} placeholder="Age" />
<p>Name: {user.name}, Age: {user.age}</p>
</div>
);
}
State is a fundamental concept in React, enabling components to maintain dynamic and interactive UIs.
Passing Data
There are cases when you want to pass the data from parent to child. Let's understand this while creating a list app and how we can pass the data to child components and use it. Here's how we can do it:
Suppose we have a component calledNote.js
which is connected to ourApp.js
:
import React, { useState } from 'react';
// Child component
import SingleNote from './SingleNote';
function Note() {
const [notes, setNotes] = useState([]);
const [curNotes, setCurNotes] = useState("");
function updateCurNote(event) {
setCurNotes(event.target.value);
}
function addNotes() {
const newNote = [...notes, curNotes];
setNotes(newNote);
}
return (
<>
<input type="text" onChange={updateCurNote} />
<button onClick={addNotes}>Submit</button>
<ul>
{notes.map((note, i) => {
{/* Sending the data to child */}
return (<li key={i}><SingleNote note={note}/></li>)
})}
</ul>
</>
);
}
export default Note;
State Management:
notes
: An array to store all the notes.curNotes
: A string to store the current input note.
Handlers:
updateCurNote(event)
: Updates thecurNotes
state whenever the user types into the input field.addNotes()
: Adds the current note (stored incurNotes
) to thenotes
array and updates thenotes
state.
Rendering:
An input field to capture the user's note, with an
onChange
event that triggersupdateCurNote
.A submit button that, when clicked, calls
addNotes
to add the current note to the list.A list (
ul
) that displays all notes. Each note is rendered as a list item (li
) and passed as a prop to theSingleNote
child component.
Child component:
import React from 'react';
// Destructuring to directly access notes.
function SingleNote({note}) {
return (
<>
{note}
</>
)
}
export default SingleNote;
Else we had to writeprops
inside the parenthesis and inside returnprops.note
, like this:
import React from 'react';
function SingleNote(props) {
return (
<>
{props.note}
</>
)
}
export default SingleNote;
Passing Data From Child To Parent
We understood how we can pass the data from parent to child, but what if we wanted to pass the child data to parent instead? There can be many use cases related to this.
Let's create a counting app again and understand how we can create such a flow:
// Parent.js
import React, { useState } from 'react'
import Child1 from './Child1';
import Child2 from './Child2';
function Parent() {
const [countInParent, setCountInParent] = useState(0);
function updateCountInParent(count) {
setCountInParent(count);
}
return (
<>
<p>Inside parent: {countInParent}</p>
{/* A callback function from where we will take and store our data */}
<Child1 onCountUpdate={updateCountInParent}/>
{/* Passing the current value to the sibling of child1 */}
<Child2 countFromParent={countInParent}/>
</>
);
}
export default Parent;
State Management:
countInParent
: A state variable in theParent
component to store a count value, initialized to 0.
Handlers:
updateCountInParent(count)
: A function that updates thecountInParent
state with a new count value passed as an argument.
Rendering:
A paragraph (
p
) that displays the current value ofcountInParent
.The
Child1
component, which is passed a proponCountUpdate
that references theupdateCountInParent
function. This allowsChild1
to update the count in the parent component.The
Child2
component, which is passed a propcountFromParent
that holds the current value ofcountInParent
. This allowsChild2
to access and use the count value from the parent component.
// child1.js
import React, { useState } from 'react'
function Child1(props) {
const [countInChild1, setCountInChild1] = useState(0);
function updateCountInChild1() {
setCountInChild1(countInChild1 + 1);
// Sending back the data to parent in callback
props.onCountUpdate(countInChild1 + 1);
}
return (
<>
<p>Inside child 1: {countInChild1}</p>
<button onClick={updateCountInChild1}>increment</button>
</>
);
}
export default Child1;
State Management:
countInChild1
: A state variable in theChild1
component to store a count value, initialized to 0.
Handlers:
updateCountInChild1()
: A function that increments thecountInChild1
state by 1 and then calls theonCountUpdate
prop function (passed from the parent) with the updated count value (countInChild1 + 1
).
Rendering:
A paragraph (
p
) that displays the current value ofcountInChild1
.A button that, when clicked, calls
updateCountInChild1
to increment the count and notify the parent component of the new count.
// child2.js
import React from 'react'
function Child2(props) {
return (
<>
<p>Inside child 2: {props.countFromParent}</p>
</>
)
}
export default Child2;
This setup allows Child1
to send a count update to the parent component, which then updates its state and passes the updated count to Child2
, ensuring that both child components can interact with and reflect changes in the parent component's state.
Event Handling
So far we have already seen few Event Handling's, such as onclick
: When a user clicks in that area a certain function will be called. Such as that React supports a wide range of event types:
Mouse Events:
onClick
,onDoubleClick
,onMouseEnter
,onMouseLeave
Keyboard Events:
onKeyDown
,onKeyPress
,onKeyUp
Form Events:
onChange
,onSubmit
Focus Events:
onFocus
,onBlur
Clipboard Events:
onCopy
,onCut
,onPaste
Event handling in React allows you to create interactive UIs by responding to user actions and updating the state or performing other actions based on those events.
Subscribe to my newsletter
Read articles from Syed Aquib Ali directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Syed Aquib Ali
Syed Aquib Ali
I am a MERN stack developer who has learnt everything yet trying to polish his skills 🥂, I love backend more than frontend.