DEV Community

Cover image for πŸš€ Day 10 of Learning React: My React Form Finally Became a Real CRUD App (Local Storage, Create, Update & Delete)
Bismay.exe
Bismay.exe

Posted on

πŸš€ Day 10 of Learning React: My React Form Finally Became a Real CRUD App (Local Storage, Create, Update & Delete)

πŸ“Œ 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.
  • πŸ“© errors stores 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([]);
Enter fullscreen mode Exit fullscreen mode

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 😢
Enter fullscreen mode Exit fullscreen mode

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")) || []
);
Enter fullscreen mode Exit fullscreen mode

At first, that line looked intimidating.

But after breaking it down, it made perfect sense.


🧩 Breaking It Down

First:

localStorage.getItem("users")
Enter fullscreen mode Exit fullscreen mode

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(...)
Enter fullscreen mode Exit fullscreen mode

to convert the string back into an array of objects.

Finally:

|| []
Enter fullscreen mode Exit fullscreen mode

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)
);
Enter fullscreen mode Exit fullscreen mode

This line does the opposite.

JavaScript Object
        ↓
JSON.stringify()
        ↓
String
        ↓
Saved in Local Storage
Enter fullscreen mode Exit fullscreen mode

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 uuid package
  • 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
Enter fullscreen mode Exit fullscreen mode

After installing it, I imported it into my component:

import { nanoid } from "nanoid";
Enter fullscreen mode Exit fullscreen mode

Whenever I created a new user, I generated a unique ID like this:

const newUser = {
  ...data,
  id: nanoid(),
};
Enter fullscreen mode Exit fullscreen mode

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
);
Enter fullscreen mode Exit fullscreen mode

The flow looks like this:

Click Delete
      ↓
Remove Matching User
      ↓
Update State
      ↓
Update Local Storage
      ↓
UI Updates ✨
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
  )
);
Enter fullscreen mode Exit fullscreen mode

Here's how I visualize it:

Users Array
      ↓
Loop Through Every User
      ↓
Matching ID?
      ↓
YES βœ… Replace It

NO ❌ Keep It
Enter fullscreen mode Exit fullscreen mode

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 ✨
Enter fullscreen mode Exit fullscreen mode

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.

Bismay-exe (Bismay.exe) Β· GitHub

πŸ‘‹ Hi, I’m Bismay πŸ’» Developer passionate about building clean, minimal, and elegant apps πŸš€ Focused on coding 🌱 Always learning, creating & new ideas - Bismay-exe

favicon github.com

πŸ€– 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)