Building a Tab Form Component in React
Here is a detailed breakdown and explanation of how you built the multi-step tab-based form component in React, step-by-step, along with code snippets and explanations of logic, validation, state management, and navigation.
✅ Objective
You created a multi-step Tab Form Component where:
- The user fills in profile details, selects interests, and chooses theme settings.
- Navigation between tabs is allowed only if the current tab is valid.
- The form is broken into 3 tabs: Profile, Interests, and Settings.
✅ 1. Overall State and Structure (Tabs.js)
🧠 Core States
const [activeTabIndex, setActiveTabIndex] = useState(0); // Track current tab const [data, setData] = useState({ name: "Yogesh Arya", age: "20", email: "yogesh@gmil.com", interests: ["Drawing"], theme: "dark", }); const [errors, setErrors] = useState({});
- activeTabIndex: Controls which tab is currently active.
- data: Holds the form data shared across all tabs.
- errors: Holds validation error messages for each field.
✅ 2. Tab Configuration with Validation Logic
const tabs = [ { name: "Profile", component: Profile, validate: () => { const err = {}; if (!data.name || data.name.length < 2) err.name = "Invalid Name"; if (!data.age || data.age < 18) err.age = "Invalid Age"; if (!data.email || data.email.length < 2) err.email = "Invalid Email"; setErrors(err); return !(err.name || err.age || err.email); }, }, { name: "Interests", component: Interests, validate: () => { const err = {}; if (data.interests.length < 1) err.interests = "Invalid Interests"; setErrors(err); return !err.interests; }, }, { name: "Settings", component: Settings, validate: () => true, // No validation }, ];
Each tab:
- Has a name, a component, and a validate function.
- validate() is run before moving to the next tab or switching manually.
✅ 3. Dynamic Component Rendering
const TabBody = tabs[activeTabIndex]?.component; <TabBody data={data} setData={setData} errors={errors} />
- The active component (Profile, Interests, or Settings) is rendered based on activeTabIndex.
✅ 4. Navigation Logic
const handlePrev = () => { setActiveTabIndex((prev) => prev - 1); }; const handleNext = () => { if (tabs[activeTabIndex].validate()) { setActiveTabIndex((prev) => prev + 1); } }; const handleSubmit = () => { console.log("Submitting:", data); };
- Next: Proceeds only if current tab is validation passes.
- Prev: Goes back without validation.
- Submit: Shown only on the last tab.
✅ 5. Tab Header Buttons
<div className="tabs"> {tabs.map((tab, index) => ( <button key={index} onClick={() => tabs[activeTabIndex].validate() && setActiveTabIndex(index) } > {tab.name} </button> ))} </div>
- Clicking a tab header will only change tabs if the current tab is valid.
- Prevents skipping validation by jumping directly to another tab.
✅ 6. Profile Tab (Profile.js)
Purpose: Enter name, age, and email.
<input type="text" name="name" value={data.name} onChange={handleChange} /> {errors.name && <p className="error">{errors.name}</p>}
Logic:
- Controlled inputs using data and setData.
- Shows error messages based on errors.
✅ 7. Interests Tab (Interests.js)
Purpose: Choose one or more interests via checkboxes.
<input type="checkbox" checked={data.interests.includes("Coding")} onChange={(e) => handleChangeInterests(e, "Coding")} />
Logic:
- Toggles interest selection.
- Validation ensures at least one is selected.
setData((prev) => ({ ...prev, interests: e.target.checked ? [...prev.interests, value] : prev.interests.filter((val) => val !== value), }));
✅ 8. Settings Tab (Settings.js)
Purpose: Select theme (radio button for dark or light).
<input type="radio" checked={data.theme === "dark"} name="dark" onChange={handleThemeChange} />
Logic:
- Controlled via data.theme
- Updates theme in global form data.
✅ 9. Final Buttons
{activeTabIndex > 0 && <button onClick={handlePrev}>prev</button>} {activeTabIndex < tabs.length - 1 && ( <button onClick={handleNext}>next</button> )} {activeTabIndex === tabs.length - 1 && ( <button onClick={handleSubmit}>Submit</button> )}
- Conditionally renders Prev/Next/Submit buttons based on the tab.
✅ 10. Example Form Flow
- Profile → Fill name, age (≥18), and email → Click Next
- Interests → Select at least one checkbox → Click Next
- Settings → Choose a theme → Click Submit
✅ Enhancement Ideas
- Add animations between tab transitions.
- Disable tabs that are not yet valid.
- Show step indicators (Step 1 of 3).
- Highlight tab headers with errors.