0

When I click on a new li tag, I want the classname to change to active (which works), but also remove active from the rest of the li tags (which doesn't work). document.getElementByTagName('li').classList.remove="active", doesn't work because it is saying it is not defined. Should I go about this a different way... maybe storing something different in the state?

import React, {useState, useEffect} from 'react';
import './Anime.css';

function Anime(){
    const [currentCase, setCurrentCase] = useState(0)
    function getAnime(){
        fetch('https://kitsu.io/api/edge/anime')
        .then(response => response.json())
        .then(data => console.log(data));
    }

    function currentSelector(e){
        document.getElementsByTagName('li').clasList.remove("active");
        setCurrentCase(e.target.value)
        e.target.className = "active" 
    }

    useEffect(() => {
        getAnime();
      }, []);
    
    return(
        <div className="anime">
            {/* Selectors */}
            <ul>
                <li value= {0} className="active" onClick={currentSelector}>Trending</li>
                <li value={1} onClick={currentSelector}>Action</li>
                <li value={2} onClick={currentSelector}>Adventure</li>
                <li value={3} onClick={currentSelector}>Comedy</li>
                <li value={4} onClick={currentSelector}>Drama</li>
                <li value={5} onClick={currentSelector}>Magic</li>
                <li value={6} onClick={currentSelector}>Romance</li>
            </ul>
            
        </div>
    )
}

export default Anime
1
  • 1
    You seem to have a typo clasList should have 2 "s"s. Please compare in the code snippet you provided. Additionally, why are you using the regular DOM API instead of dealing with this in React's APIs? Commented Nov 25, 2020 at 18:05

1 Answer 1

1

Don't use the usual DOM API for things like this in React, instead use React's state management and conditional rendering functionality. You already have a state variable to track the active case (currentCase), so you can just set the class name conditionally while rendering.

For each li, just check if the value of currentCase matches the value for that li and if so, give that li the class active, otherwise give a different class.

For example:

import React, {useState, useEffect} from 'react';
import './Anime.css';

function Anime(){
    const [currentCase, setCurrentCase] = useState(0)
    function getAnime(){
        fetch('https://kitsu.io/api/edge/anime')
        .then(response => response.json())
        .then(data => console.log(data));
    }

    function currentSelector(e){
        setCurrentCase(Number(e.target.value));
    }

    useEffect(() => {
        getAnime();
      }, []);
    
    return(
        <div className="anime">
            {/* Selectors */}
            <ul>
                <li value={0} className={currentCase === 0 ? "active" : ""} onClick={currentSelector}>
                    Trending
                </li>
                <li value={1} className={currentCase === 1 ? "active" : ""} onClick={currentSelector}>
                    Action
                </li>
                <li value={2} className={currentCase === 2 ? "active" : ""} onClick={currentSelector}>
                    Adventure
                </li>
                <li value={3} className={currentCase === 3 ? "active" : ""} onClick={currentSelector}>
                    Comedy
                </li>
                <li value={4} className={currentCase === 4 ? "active" : ""} onClick={currentSelector}>
                    Drama
                </li>
                <li value={5} className={currentCase === 5 ? "active" : ""} onClick={currentSelector}>
                    Magic
                </li>
                <li value={6} className={currentCase === 6 ? "active" : ""} onClick={currentSelector}>
                    Romance
                </li>
            </ul>
            
        </div>
    )
}

export default Anime

Or extract the class name logic into a function (defined within your Anime component) and call that function for each li element:

function getLiClassName(value) {
    if (value === currentCase) {
        return "active";
    }
    return "";
}

And use like this:

<li value={0} className={getLiClassName(0)} onClick={currentSelector}>
    Trending
</li>
Sign up to request clarification or add additional context in comments.

1 Comment

I was writing a very similar answer, this approach is the way to do it. If you want to simplify the code, instead of extracting a getLiClassName function, consider creating an array of the available selectors and using .map to generate the <li>s. Then you only need to write the case check once anyways :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.