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.