Reputation: 150
How can we create a stepper that is the multi-step form in Reactjs for multiple-step form submission? Currently, I am not showing component for each step
For now, I am able to return the component but it returns all the component at the same time, as I want to return component in the center for each step it passes.
Here is code for stepper which works perfectly
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import "./Stepper.scss";
const Stepper = ({ stepColor, steps, direction, currentStep }) => {
const [stepState, setStepState] = useState([]);
useEffect(() => {
let createSteps = steps.map((step, idx) => ({
description: step.label,
component: step.component,
completed: idx < currentStep - 1, // past are completed
selected: idx <= currentStep - 1, // past & present are colored
highlighted: idx === currentStep - 1 // only present is highlighted
}));
setStepState(createSteps);
}, [steps, currentStep]);
return (
<div className={`stepper-wrapper-${direction}`}>
{stepState.map(
({ selected, completed, highlighted, description, component }, idx) => (
<div className="step-wrapper" key={idx}>
<div
className={`step-number step-number-${
selected ? "active" : "disabled"
}`}
style={{ background: `${selected ? stepColor : "none"}` }}
>
{completed ? "✔" : idx + 1}
</div>
<div
className={`step-description ${
highlighted ? "step-description-active" : ""
}`}
>
{description}
</div>
{idx + 1 !== stepState.length && (
<div
className={`divider-line divider-line-${stepState.length}`}
/>
)}
<div>{component}</div>
</div>
)
)}
</div>
);
};
Stepper.propTypes = {
direction: PropTypes.string.isRequired,
steps: PropTypes.array.isRequired
};
export default Stepper;
Image how it should look alike
Upvotes: 0
Views: 120
Reputation: 1160
You have an array of steps and you render forms within map method. That means the code is being rendered for every element of an array. And thats why you have received as many forms as you have elements in array of steps. If you want to hide or to show them you should render only the form of active (or highlited) step. In other words, this part of code should be rendered only if it is about current step.
<div
className={`step-description ${
highlighted ? "step-description-active" : ""
}`}
>
{description}
</div>
{idx + 1 !== stepState.length && (
<div
className={`divider-line divider-line-${stepState.length}`}
/>
)}
<div>{component}</div>
You can find a state (ex. highlighted) describing the index of object containing data for active form and use it like
{highlighted && <div>{description}</div>
But let me be honest - I would change a lot in your code. Form is better to be a component itself and just take data from state without any tricks within render section.
UPDATE: You can replace the piece of code mentioned above with this:
{highlighted && <div
className={`step-description ${
highlighted ? "step-description-active" : ""
}`}
>
{description}
</div>}
{idx + 1 !== stepState.length && (
<div
className={`divider-line divider-line-${stepState.length}`}
/>
)}
{highlighted && <div>{component}</div>}
Upvotes: 1