Reputation:
I am building a progress bar which takes two inputs, totalSteps
and activeStep
. I am going to render a number of circles equal to the number of total steps, with the active step being grey.
I have experience mapping over an array of objects however in this case I don't have an array I am just given an integer.
I am attempting to write a function which returns a div
in a for loop but this isn't working.
const ProgressBar = (props) => {
const { activeStep, totalSteps } = props;
const displayProgressBar = () => {
for (let i = 1; i <= totalSteps; i++) {
return <div>Hello</div>;
}
};
return <div className="progressBar">{displayProgressBar()}</div>;
};
The above code only renders Hello
once even if totalSteps
is 3. Is there a way to achieve the desired results without creating an array?
Upvotes: 4
Views: 7275
Reputation: 31692
Your for
loop terminates after the first iteration because return
terminates the function call immediately. You need to accumulate the JSX elements in an array and use that instead. You also don't need the function displayProgressBar
at all.
const ProgressBar = (props) => {
const { activeStep, totalSteps } = props;
const steps = [];
for (let i = 1; i <= totalSteps; i++) {
steps.push(<div>Hello</div>);
}
return (<div className="progressBar">{ steps }</div>);
};
You should probably add an active
class or something to the activeStep
item so it is selected, change steps.push(...)
from above to:
steps.push(<div className={ i == activeStep ? "active" : "" }>Hello</div>);
Upvotes: 4
Reputation: 202915
You "...have experience mapping over an array..." then this should be a cakewalk; it is exactly the same. If the question more about how to take a number and convert it to an array, and I think it is, then a common pattern is [...Array(5).keys()]
. Once you've an array you can map it as normal in JSX.
const ProgressBar = (props) => {
const { activeStep, totalSteps } = props;
const displayProgressBar = () =>
[...Array(totalSteps).keys()].map((step) => <div key={step}>Hello</div>);
return <div className="progressBar">{displayProgressBar()}</div>;
};
It may be simpler to just inline the array though.
const ProgressBar = (props) => {
const { activeStep, totalSteps } = props;
return (
<div className="progressBar">
{[...Array(totalSteps).keys()].map((step) => {
// logic to compare against activeStep
return (
<div key={step}>Hello</div>
))}}
</div>
);
};
Upvotes: 1
Reputation: 9063
Well you literally need an array of elements, so what's wrong with creating an array?
const ProgressBar = (props) => {
const { activeStep, totalSteps } = props;
const steps = (new Array(totalSteps))
.fill(undefined)
.map((step, index) => (
// If the step is active (or past) step, give it a grey background
<div key={index} style={{ backgroundColor: index + 1 <= activeStep ? 'grey' : 'white' }}>
{index+1}
</div>
));
return <div className="progressBar">{steps}</div>;
};
Something like this will create an array of elements and colour them accordingly
Upvotes: 0
Reputation: 196026
You could create an array on the fly just for this
const ProgressBar = (props) => {
const { activeStep, totalSteps } = props;
const steps = new Array(totalSteps).fill().map((_,index)=>{
const stepIndex = index+1;
const activeClassName = stepIndex === activeStep ? 'active':undefine;
return <div className={activeClassName}>{stepIndex}</div>
});
return <div className="progressBar">{display}</div>;
};
Upvotes: 0