useState Hook & Immutable State03-09-2023
useState is a hook in React that allows you to add state to your functional components. It is used when you need to store and manage state data in your application, such as user input, API responses, or to show/hide components.
In React, state refers to the data that determines the behavior of your application and can change over time. By using useState, you can define a piece of state data and a function that updates that data. When the state data is updated, React automatically re-renders the component and any child components that depend on that data.
When state data changes in a component, React uses its virtual DOM to determine what parts of the real DOM need to be updated. React compares the previous state of the virtual DOM with the current state to identify any differences. This process is known as reconciliation.
Here's an example of using the useState hook to manage the visibility of a modal dialog box:
import React, { useState } from 'react';
function ModalButton() {
const [showModal, setShowModal] = useState(false);
const handleOpenModal = () => setShowModal(true);
const handleCloseModal = () => setShowModal(false);
return (
<div> {/* always visible */}
<button onClick={handleOpenModal}>Open Modal</button>
{/* expression must evaluate to true && true to show */}
{showModal && (
<>
<div>
<h2>Modal Title</h2>
<p>Modal content goes here</p>
<button onClick={handleCloseModal}>Close</button>
</div>
</>
)}
</div>
);
}
An event handler is supposed to be either a function or a function reference. A function call will not work here.
When the "Open Modal" button is clicked, handleOpenModal function is called and updates the showModal state data by calling setShowModal(true). This causes the modal dialog box to be displayed, since showModal is now true.
When the "Close" button in the modal dialog box is clicked, handleCloseModal is called and updates the showModal state data by calling setShowModal(false). This causes the modal dialog box to be hidden again, since showModal is now false.
When working with the useState hook, it's important to understand the difference between mutable and immutable state. Mutable state is state that can be changed directly, while immutable state is state that cannot be changed directly but must be replaced with a new version.
In React, it's generally recommended to use immutable state as much as possible, as it helps to avoid bugs and make your code more predictable. This means that instead of directly modifying state, you should create a new copy of the state with the desired changes.
Let's say we have a simple React component that displays a list of items and allows the user to add new items to the list. We could implement this component with either mutable or immutable state.
Here's an example of the component using mutable state:
import React, { useState } from 'react';
function MutableList() {
const [items, setItems] = useState(['First Item']);
function handleAddItem() {
items.push('New Item'); {/* Directly modifying the state array */}
setItems(items); // {/* Updating the state with the modified array */}
}
return (
<div>
<ul>
{items.map(item => (
<li key={Math.random()}>{item}</li>
))}
</ul>
<button onClick={handleAddItem}>Add Item</button>
</div>
);
}
We directly modify the
itemsarray by using thepushmethod to add a new item. This can lead to unexpected behavior and bugs, especially if other components are also modifying the same array.
And here's an example of the same component using immutable state:
function ImmutableList() {
const [items, setItems] = useState([]);
function handleAddItem() {
{/* Use the spread syntax (...) and make a copy of the original state */}
const newItems = [...items, 'New Item'];
setItems(newItems); {/* Update the state with the new array */}
}
return (
<div>
<ul>
{items.map(item => (
<li key={Math.random()}>{item}</li>
))}
</ul>
<button onClick={handleAddItem}>Add Item</button>
</div>
);
}
newItems by spreading the existing items array and adding the new item to the end. By doing this, all the references of items won't be affected until we use setItems, and thus changes made to the state are predictable and consistent.Overall, using immutable state gives you control over your code, helps to avoid bugs, and makes your code more maintainable.