π Missed Day 9? I explored how React Hook Form handles validation, why the errors object exists, and how register() and handleSubmit() work together to prevent invalid form submissions. You can **read it here* and then come back. I'll wait. βοΈ*
Yesterday, I finally built a form that could collect user information.
It worked.
I could enter a name, email, mobile number, and image URL.
Click Add User...
The new user appeared on the screen.
Everything looked perfect.
Until I refreshed the page.
Every single user disappeared.
π
That's when I realized something.
React wasn't losing my data...
It was doing exactly what I asked it to do.
The problem was that I was only storing everything in state.
Today, I learned how to make my application actually remember dataβeven after refreshing the browser.
And by the end of the class, my simple form had turned into my first CRUD application. π
π§ Quick Recap
Yesterday's big question was:
How can I make forms smarter with validation?
Here's what I learned on Day 9:
- β React Hook Form simplifies form handling.
- β οΈ Validation rules prevent invalid input.
- π©
errorsstores validation messages. - π
register()connects inputs to React Hook Form. - π
handleSubmit()only runs when validation passes.
Today, we're answering a different question:
How can my application actually remember user data? π€
πΎ The Problem With React State
At first, I stored my users like this:
const [users, setUsers] = useState([]);
Whenever I submitted the form, a new user appeared instantly.
Everything seemed fine.
Until I pressed refresh.
Add User
β
User Appears
β
Refresh Browser
β
Everything Disappears πΆ
That wasn't React making a mistake.
It was simply because React state only lives while the application is running.
Refreshing the page starts everything from scratch.
π¦ Enter Local Storage
That's where I discovered Local Storage.
Unlike React state, Local Storage is built into the browser.
It stores data even after refreshing the page.
Instead of starting with an empty array, I initialized my state like this:
const [users, setUsers] = useState(
JSON.parse(localStorage.getItem("users")) || []
);
At first, that line looked intimidating.
But after breaking it down, it made perfect sense.
π§© Breaking It Down
First:
localStorage.getItem("users")
tries to read previously saved users.
But Local Storage stores everything as strings.
That's why React can't use it directly.
So I used:
JSON.parse(...)
to convert the string back into an array of objects.
Finally:
|| []
acts as a fallback.
If no users exist yet, React simply starts with an empty array.
πΎ Saving Users
Loading data is only half of the story.
Whenever I created a new user, I also needed to save it.
localStorage.setItem(
"users",
JSON.stringify(arr)
);
This line does the opposite.
JavaScript Object
β
JSON.stringify()
β
String
β
Saved in Local Storage
Now, even after refreshing the page...
My users were still there.
That was a really satisfying moment.
π Every User Needs a Unique Identity
While building the CRUD application, I ran into another small but important problem.
Every user needed a way to be uniquely identified.
Without a unique ID, React wouldn't know exactly which user I wanted to update or delete.
There are several ways to generate unique IDs. Some common options are:
- Using a database-generated ID
- JavaScript's built-in
crypto.randomUUID() - The popular
uuidpackage - The lightweight nanoid package
For this project, I used nanoid because it's simple, lightweight, and generates unique IDs with very little setup.
π¦ Installing Nano ID
npm install nanoid
After installing it, I imported it into my component:
import { nanoid } from "nanoid";
Whenever I created a new user, I generated a unique ID like this:
const newUser = {
...data,
id: nanoid(),
};
Now every user has its own unique identifier.
That ID becomes incredibly useful later.
When I click Update or Delete, React can easily find the correct user by comparing IDs instead of relying on things like the user's name or their position in the array.
It might seem like a tiny detail, but adding unique IDs makes managing collections of data much more reliableβespecially as applications grow larger.
β Deleting Users
The next feature I added was deleting users.
The logic turned out to be surprisingly clean.
const filteredUsers = users.filter(
(user) => user.id !== id
);
The flow looks like this:
Click Delete
β
Remove Matching User
β
Update State
β
Update Local Storage
β
UI Updates β¨
One click...
And the selected card disappeared.
βοΈ Reusing the Same Form for Updates
This was probably the coolest part of today's project.
My first thought was:
"Updating a user probably needs another form."
It turns out...
It didn't.
I reused the exact same form for both creating and updating users.
That felt much cleaner than building two separate forms.
π Filling the Form Automatically
When I clicked Update, I passed the selected user's data into the form.
defaultValues: updatedData
That tiny line made React Hook Form automatically fill every input.
Instead of seeing empty fields...
I immediately saw the existing user's information.
It felt like the form already knew what I wanted to edit.
π Updating Only One User
Saving the updated data was another interesting part.
Instead of replacing the whole array, I only replaced the matching user.
setUsers((prev) =>
prev.map((user) =>
user.id === updatedData.id
? { ...data }
: user
)
);
Here's how I visualize it:
Users Array
β
Loop Through Every User
β
Matching ID?
β
YES β
Replace It
NO β Keep It
Only one object changes.
Everything else stays exactly the same.
That made map() feel much more practical than when I first learned it.
π§ My Mental Model
Today's project finally connected a lot of concepts I'd learned over the past few days.
Fill Form
β
React Hook Form Validates
β
User Added
β
Save in State
β
Save in Local Storage
β
Render User Cards
β
Update or Delete User
β
UI Updates Automatically β¨
Seeing everything work together made the project feel much more like a real application instead of isolated React examples.
π‘ My Biggest Takeaways Today
- πΎ React state disappears after a refresh, but Local Storage doesn't.
- π¦
JSON.parse()converts stored strings back into JavaScript objects. - π
JSON.stringify()prepares objects before saving them. - π
nanoid()makes it easy to generate unique IDs. - βοΈ The same form can be reused for both creating and updating users.
- π
map()makes updating a single object inside an array surprisingly clean.
π Learning Source
I'm currently learning React through the React Cohort 3.0 by Devendra Dhote at Sheriyans Coding School.
This article is based on my own class notes, code experiments, and understanding after today's session. Writing these posts helps me reinforce what I've learned, and hopefully helps other beginners following a similar path.
If I've misunderstood anything, I'd genuinely appreciate corrections in the comments. π
π Final Thoughts
Today's project felt different from the previous ones.
Instead of learning a single React concept, I finally saw several concepts working together.
State stored the data.
React Hook Form handled user input.
Local Storage made the data survive page refreshes.
map() updated individual users.
filter() removed them.
For the first time, it felt like I wasn't just writing React codeβI was building something that behaved like a real application.
Tomorrow's topic is Context API, and I'm curious to see how React lets components share data without passing props through every level.
See you on Day 11! π
π¬ When you built your first CRUD application, what feature felt the most satisfying to implementβCreate, Update, Delete, or saving data with Local Storage?
I'd love to hear your experience in the comments. π
If you're following along with this series, you can also find me on GitHub, where I'll be sharing my projects and documenting my progress.
π€ AI Disclosure: This article is based on my own React learning journey, class notes, code experiments, and understanding. I used ChatGPT to help improve the writing, structure, and readability of this post. I reviewed and verified the technical explanations before publishing, and I take responsibility for everything shared here.
Thanks for reading! π
Top comments (0)