React JS - All about States
Essential State Concepts for Creating Powerful React Apps

At Code Subtle, we empower aspiring web developers through personalized mentorship and engaging learning resources. Our community bridges the gap between theory and practice, guiding students from basics to advanced concepts. We offer expert mentorship and write interactive, user-friendly articles on all aspects of web development. Join us to learn, grow, and build your future in tech!
State
State is an object that represents the current situation or data of a component at a given time. It holds dynamic values that can change over time (as opposed to props, which are passed from parent components and are generally static or immutable). When state changes, the component re-renders to reflect the new state.
import React, { useState } from 'react';
function Counter() {
// Declare a state variable called count, initialized to 0
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
In the above example, count is the state variable, and setCount is the function used to update its value.
1. How State Works: Key Concepts
a. Initialization of State
State is typically initialized using the useState hook (in function components).
const [value, setValue] = useState(initialValue);
b. Updating State
State should never be updated directly (i.e., mutating the object). Instead, you use state setter function (in function components).
setCount(count + 1);
React uses a shallow merge when you call setState in class components. Only the properties specified in the setState call will be updated, and others will remain unchanged.
c. Asynchronous Nature of State Updates
State updates in React are asynchronous. React batches multiple state updates for performance reasons, especially in event handlers.
Function Components: You can also pass a function to the state setter function:
setCount((prevCount) => prevCount + 1);
d. State and Re-rendering
When the state of a component changes, React triggers a re-render of that component. This allows the UI to update based on the latest state. If parent renders then children's also renders in React, Parent of the parent will not be rendered.
2. Managing Complex State
a. State as an Object
In more complex scenarios, you might have a state object with multiple properties. In such cases, it’s important to merge the new state with the existing state rather than replacing the entire object.
Function Components: When using the useState hook with objects, you need to spread the existing state to avoid losing properties:
setState((prevState) => ({ ...prevState, name: 'Vitthal' }));
b. State as an Array
You can also manage arrays in state. Use array methods like map, filter, concat, and spread to update arrays immutably.
const [items, setItems] = useState([]);
setItems([...items, newItem]); // Adding a new item
3. Lifting State Up
When multiple components need to share or synchronize state, the state should be "lifted up" to the nearest common ancestor component. This allows the parent component to manage the state and pass it down to the child components as props.
"lifting the state up" is a design pattern that involves moving the state from a child component to a parent component. This is done to make the state accessible to multiple child components, or to make it easier to manage the state from a single location.
Example:
function ParentComponent() {
const [sharedState, setSharedState] = useState('Shared State');
return (
<div>
<ChildComponent1 sharedState={sharedState} />
<ChildComponent2 setSharedState={setSharedState} />
</div>
);
}
Here, sharedState is passed down as a prop to both child components.
4. Common State Patterns
a. Derived State
Avoid directly storing derived values in the state. If a value can be computed from existing state or props, it’s better to derive it in the render method rather than store it in state.
function Component({ items }) {
const itemCount = items.length; // Derived from props
return <p>Total items: {itemCount}</p>;
}
b. Conditional State Updates
Sometimes, you need to conditionally update state based on certain criteria.
if (count < 10) {
setCount(count + 1);
}
5. Best Practices for State
Keep state minimal: Only store data that’s necessary for rendering. Avoid storing derived or redundant values in the state.
Use state immutably: Always return new objects or arrays when updating the state to avoid side effects.
Avoid deep state nesting: Flatten state as much as possible to simplify updates and avoid performance issues.
Batch state updates: If you need to make multiple state changes at once, batch them to minimize renders.
6. State and Performance
While state is a powerful tool for managing UI, it can also lead to performance bottlenecks if misused. Here are some tips:
Memoization: Use
useMemooruseCallbackto memoize heavy computations or functions that depend on state to avoid unnecessary re-renders.Avoid redundant re-renders: Overuse of state or complex state updates can cause unnecessary re-renders, affecting performance.
7. Example : Input Field
Let's create an example where we manage the state of an input field.
import { useState } from 'react';
function TextInput() {
// Initialize state with an empty string
const [text, setText] = useState('');
return (
<div>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<p>You typed: {text}</p>
</div>
);
}
export default TextInput;
We initialize the
textstate with an empty string.The input field's value is controlled by the
textstate.The
onChangeevent updates thetextstate with the input field's current value.We display the current input value in a
<p>element.
8. Example : Toggle
Let's create a component to toggle between two states.
import { useState } from 'react';
function Toggle() {
// Initialize state with true
const [isOn, setIsOn] = useState(true);
return (
<div>
<p>{isOn ? 'ON' : 'OFF'}</p>
<button onClick={() => setIsOn(!isOn)}>
{isOn ? 'Turn Off' : 'Turn On'}
</button>
</div>
);
}
export default Toggle;
We initialize the
isOnstate withtrue.We display "ON" or "OFF" based on the
isOnstate.We provide a button to toggle the state. When clicked, the button calls
setIsOnwith the opposite of the current state.
//hooks
//useState
//useEffect
//useState is a hook which you can call as a function. \
//it takes default value as a argument
//useState(defaultValue) -> it'll return an array
//[stateValue, functionToUpdateThatStateValue];
//In react we cannot use normal variables
//to change the UI
//state == data
//When state change -> our component will re-render -> UI
import { useState } from "react";
function StateSimple() {
const [name, setName] = useState("vitthal");
//console.log(name, setName);
function updateName() {
if (name === "vitthal") {
setName("korvan");
} else {
setName("vitthal");
}
}
return (
<>
<h1>{name}</h1>
<button onClick={updateName}>Change Name</button>
</>
);
}
export default StateSimple;
9. Counter App using Callback function
import { useState } from "react";
import "./counter.css";
function Counter() {
let [count, setCount] = useState(0);
return (
<>
<h1 className="count">{count}</h1>
<button
onClick={() => {
setCount((prev)=>prev+1)
}}
className="btn"
>
Increase
</button>
<button
onClick={() => {
setCount((prev) => prev - 1);
}}
className="btn"
>
Decrease
</button>
<button
onClick={() => {
setCount(0);
}}
className="btn"
>
Reset
</button>
</>
);
}
export default Counter;
10. Update State in Array
for unique ID of an array elements we use command: npm i uuild
Why creating keys on the fly is a problem: When you create keys on the fly, you're essentially generating a new key every time the component is rendered. This can lead to:
Performance issues: React has to re-render the entire list every time the keys change, which can be slow and inefficient.
Unexpected behavior: If the keys change, React may not be able to correctly identify which components to update or remove, leading to unexpected behavior.
import {v4 as uuid} from "uuid";
fruits.map((fruit)=>(<li key={uuid()}>{fruit}</li>
import { useState } from "react";
import {v4 as uuid} from "uuid";
function ArrayState() {
const [fruits, setFruits]=useState(['Mango','Apple','Banana','Chikoo']);
const AddFruit=()=>{
//setFruits([...fruits,'Orange'])
// setFruits((prevFruits)=>{
// return [...prevFruits, 'Orange']
// })
setFruits((prevfruits)=>[...prevfruits, 'Orange'])
}
return <>
<ul>
{
fruits.map((fruit)=>(
<li key={uuid()}>{fruit}</li>
))
}
</ul>
<button onClick={AddFruit}>Add fruit</button>
</>;
}
export default ArrayState;
11. Update State in Objects
import { useState } from "react";
function ObjectState() {
const [person, setPerson] = useState({
id:1,
fName:'Vitthal',
lName:'Korvan',
email:'vitthalkorvan@gmail.com',
mob:'9876543210',
age:24
});
const IncreaseAge =()=>{
// setPerson((prevPerson)=>{
// return {...prevPerson, age:prevPerson.age+1}
// })
setPerson((prevPerson)=> ({...prevPerson, age:prevPerson.age+1}))
}
return (
<>
<div >
<p>FirstName : {person.fName}</p>
<p>LastName : {person.lName}</p>
<p>Email : {person.email}</p>
<p>Mobile : {person.mob}</p>
<p>Age : {person.age}</p>
<button onClick={IncreaseAge}>Increase Age</button>
</div>
</>
);
}
export default ObjectState;
Some Applications
Example 1: Create and Update object
//App.jsx
import { useState } from "react";
import "./App.css";
import Users from "./Users";
function App() {
const [users, setUser] = useState([
{ id: 1, fname: "vitthal", lname: "korvan", age: 24 },
{ id: 2, fname: "Mahesh", lname: "boga", age: 24 },
{ id: 3, fname: "jagannath", lname: "patta", age: 24 },
{ id: 4, fname: "arpit", lname: "gupta", age: 24 }
]);
return <>
<Users users={users}/>
</>;
}
export default App;
//Users.jsx
import React from "react";
import "./App.css";
import User from "./User";
function Users({users}) {
return (
<>
{
users.map((user)=>{
return <User {...user} key={user.id}/>
})
}
</>
);
}
export default Users
//User.jsx
import "./App.css"
function User({firstname, lastname, age}) {
return (
<>
<div className="user">
<p>firstName: {firstname}</p>
<p>lastName: {lastname}</p>
<p>age: {age}</p>
</div>
</>
);
}
export default User
Example 2: Increase age and Delete user Using Object
// App.jsx
import { useState } from "react";
import "./App.css";
import Users from "./Users";
function App() {
const [users, setUser] = useState([
{ id: 1, fname: "vitthal", lname: "korvan", age: 24 },
{ id: 2, fname: "Mahesh", lname: "boga", age: 24 },
{ id: 3, fname: "jagannath", lname: "patta", age: 24 },
{ id: 4, fname: "arpit", lname: "gupta", age: 24 },
]);
const IncreaseAge = (id) => {
setUser((prevState) => {
return prevState.map((user) => {
if (user.id === id) {
return { ...user, age: user.age + 1 };
} else {
return user;
}
});
});
};
// const DeleteUser=(id)=>{
// setUser((prevState)=>{
// return prevState.filter(user=>{
// return user.id !== id
// })
// })
// }
const DeleteUser =(id)=> setUser(prevState =>
prevState.filter(user => user.id !==id))
return (
<>
<Users users={users} IncreaseAge={IncreaseAge} DeleteUser =
{DeleteUser}/>
</>
);
}
export default App;
//Users.jsx
import React from "react";
import "./App.css";
import User from "./User";
//Prop Drilling
function Users({users, IncreaseAge, DeleteUser}) {
return (
<>
{/* {users.map((user) => (
<div key={uuid()} className="user">
<p>firstName: {user.fname}</p>
<p>lastName: {user.lname}</p>
<p>age: {user.age}</p>
</div>
))} */}
{
users.map((user)=>{
return <User {...user} key={user.id}
IncreaseAge={IncreaseAge} DeleteUser = {DeleteUser}/>
})
}
</>
);
}
export default Users
//User.jsx
import "./App.css";
function User({ firstname, lastname, age, id, IncreaseAge, DeleteUse})
{
return (
<>
{/* <div key={uuid()} className="user">
<p>firstName: {userDetail.fname}</p>
<p>lastName: {userDetail.lname}</p>
<p>age: {userDetail.age}</p>
</div> */}
<div className="user">
<p>firstName: {firstname}</p>
<p>lastName: {lastname}</p>
<p>age: {age}</p>
<button onClick={() => IncreaseAge(id)}>Increase Age</button>
<button onClick={() => DeleteUser(id)}>Delete User</button>
</div>
</>
);
}
export default User;
ToDo List App - Todo List
GitHub Link - All About States






