Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate through DOM elements in react and add/remove classes?

I am beginner to react and I am unable to iterate through div elements.
Each of these div elements (shown in the code) have a common className="step" initially but once the button Next is clicked I want 1st div to have className="step current" . Once Next is clicked again 1st div element should have className="step done"(remove current and append done) and 2nd div element would have classname="step current"

I was able to toggle the className from "step" to "step current" in the following code but I am facing difficulty to traverse the div elements and add or remove the class.

class NavBar extends React.Component{
    state = {
        addClass : false
    }
    handleClick=()=>{
        this.setState({addClass: !this.state.addClass});
    }
    render(){
        let arrowClass = ["step"];
        if(this.state.addClass){    
            arrowClass.push("current");
        }
        return(
            <div id="navbar-div">
                <div className="arrow-steps clearfix">
             1.       <div className={arrowClass.join(' ')}>
                        <span> Step1</span>
                    </div>
             2.       <div className={arrowClass.join(' ')}>
                        <span>Step2</span>
                    </div>
             3.       <div className={arrowClass.join(' ')}>
                        <span> Step3</span>
                    </div>
             4.       <div className={arrowClass.join(' ')}>
                        <span>Step4</span>
                    </div>
             5.       <div className={arrowClass.join(' ')}>
                        <span>Step5</span>
                    </div>
                </div>
                <div className="nav clearfix">
                    <a href="#" className="prev">Previous</a>
                    <a href="#" className="next pull-right" onClick={this.handleClick}>Next</a>
                </div>
                </div>
        );
    }
}

ReactDOM.render(
  <NavBar />,
  document.getElementById("root")
);
.current {
  font-weight: bold;
}
.done {
  color: #aaa;
}
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>

The classes step, current and done are defined in the css file.

like image 487
user7098526 Avatar asked Oct 17 '25 11:10

user7098526


1 Answers

Rather than writing the steps explicitly, put them in an array, and then remember where you are within that array with an indexing variable. Here's the minimal-changes approach to doing that with your code (see comments):

class NavBar extends React.Component{
    state = {
        steps: ["Step1", "Step2", "Step3", "Step4"],
        current: 0 // <== Step1 is the current step
    }
    prevClick = () => {
        // Move to previous step, note we use the callback version of setState,
        // see https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
        this.setState(({current}) => ({current: Math.max(0, current - 1)}));
    }
    nextClick = () => {
        // Move to next step
        this.setState(({steps, current}) => ({current: Math.min(steps.length - 1, current + 1)}));
    }
    render() {
        // Get the steps and the current index
        const {current, steps} = this.state;
        // Render them, checking the position of the step (`index`) relative to `current`
        // and outputting the relevant class name.
        // I changed your `div`s to an ordered list so we get automatic numbering
        return (
            <div id="navbar-div">
                <div>{current}</div>
                <ol className="arrow-steps clearfix">
                    {steps.map((step, index) =>
                        <li key={index} className={`step ${index < current ? 'done' : index == current ? 'current' : ''}`}>{step}</li>
                    )}
                </ol>
                <div className="nav clearfix">
                    <a href="#" className="prev" onClick={this.prevClick}>Previous</a>
                    <a href="#" className="next pull-right" onClick={this.nextClick}>Next</a>
                </div>
            </div>
        );
    }
}

ReactDOM.render(
  <NavBar />,
  document.getElementById("root")
);
.current {
  font-weight: bold;
}
.done {
  color: #aaa;
}
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>

Obviously, that just shows the basic approach, you'll want to modify it. If you have any information other than just the step text, you might make the array entries objects rather than just strings.

(Note: Using index as the key on those lis is only valid if you don't add/remove entries in the array of steps.)


Side note: As Murali Krishna pointed out, you had class rather than className on the div containing the previous/next links and on those links; I've changed those to className above.

like image 98
T.J. Crowder Avatar answered Oct 19 '25 01:10

T.J. Crowder