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
- 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.