6/18/2025 · Portfolio Admin

React Forms are Easy… Until They Aren’t: My Journey with Sampark

Synced from Medium RSS

“It’s just a form. How hard could it be?”
That’s what I thought — until I built one that needed to adapt to multiple user roles, handle XLSX uploads, validate itself dynamically, and interact with a .NET backend.
Spoiler: It wasn’t easy.

Why I’m Writing This?

I’ve been working on a real-world onboarding dashboard called Sampark, where joinees fill out forms, HR reviews them, hiring managers assign buddies, and admins oversee the entire workflow.

From a distance? Just another form.
But up close? A layered mess of:

  • User roles (admin, HR, hiring manager)
  • Conditional logic
  • Autocomplete fields from APIs
  • XLSX file parsing
  • Modal reuse between “view”, “edit”, and “RAG connect”
  • Multipart form submission with .NET

This is that story.
And if you’re building forms in React, you’re going to want to read this all the way.

The Mission

Build a unified form component that:

  • Supports create, view, and edit modes
  • Reacts to user role (Admin, Hiring Manager, People Partner)
  • Validates important fields (like name, phone, and status)
  • Recommends team members via autocomplete
  • Accepts .xlsx/.csv bulk uploads and parses into JSON
  • Submits to a .NET backend in multipart/form-data format.

Real Challenges We Faced

Here’s a breakdown of the pain points and how we solved them:

| Challenge         | Description                                                       | Tech Solution                          |
|------------------|-------------------------------------------------------------------|----------------------------------------|
| Dynamic Fields | Show/hide recommendations based on team selection | `useEffect` + conditionally rendered MUI inputs |
| File Upload | Accept XLSX and convert to usable JSON | `SheetJS (xlsx)` for parsing |
| Role Conditions | Only specific fields editable per role | Context API + field-level conditionals |
| Autocomplete APIs | Autocomplete values from team-specific recommendations | Axios + local caching |
| Multipart Format | Send complex form with file + JSON to .NET | `FormData()` + header setup |
| Modal Reuse | Use same modal for View, Edit, and Create | Prop-driven behavior switch |

Code Examples

  1. File Upload + XLSX Parsing
const handleFileUpload = (e) => {
const file = e.target.files[0];
const reader = new FileReader();

reader.onload = (evt) => {
const workbook = XLSX.read(evt.target.result, { type: "binary" });
const sheet = workbook.Sheets[workbook.SheetNames[0]];
const parsedData = XLSX.utils.sheet_to_json(sheet);
setParsedData(parsedData); // push this to your table
};

reader.readAsBinaryString(file);
};

2. Dynamic Autocomplete Based on Team

<Autocomplete
options={teamHeads.map((u) => `${u.name} (${u.email})`)}
value={form.recruiter}
onChange={(e, val) => setForm({ ...form, recruiter: val })}
renderInput={(params) => (
<TextField {...params} label="Recruiter Manager" variant="outlined" />
)}
/>

3. Role-Specific Form Field Enable/Disable

<TextField
label="RAG Rating"
value={form.ragRating}
disabled={userRole !== "HiringManager" && userRole !== "PeoplePartner"}
onChange={(e) => setForm({ ...form, ragRating: e.target.value })}
/>

4. Submitting in multipart/form-data

const handleSubmit = async () => {
const formData = new FormData();
Object.entries(form).forEach(([key, value]) => {
if (value !== null && value !== undefined) {
formData.append(key, value);
}
});

try {
await axios.post("/api/joinee", formData, {
headers: { "Content-Type": "multipart/form-data" }
});
alert("Form submitted successfully!");
} catch (err) {
console.error("Submission failed:", err);
}
};

Common Pitfalls I Hit

  • Autocomplete didn’t clear properly when switching teams → solution: reset inputValue on change
  • FileReader sync delay → always wrap readAsBinaryString in proper onload
  • Role logic clashing with disabled fields → break form into smaller logical blocks
  • Backend rejecting data → align field names exactly as expected (teamGroupName, not team_group_name)
  • FormData not working with arrays → stringified JSON or custom backend parsing needed.

What I Learned

Building this taught me that forms are one of the hardest UI components to get right — especially in real business environments.

  • Validation should be modular and role-driven
  • Controlled components > uncontrolled chaos
  • Autocomplete is easy until you want to pre-fill, search, reset, and validate at the same time
  • File upload flows are full-stack problems, not just frontend ones.

Final Words

If you’re working on dynamic forms, don’t let the UI fool you. A form that adapts to multiple roles, conditions, file types, and backend rules is one of the most complex components in any app.

And it’s also where you really become a React developer.