Home > database >  How to show one component and hide others using useState and useEffect?
How to show one component and hide others using useState and useEffect?

Time:08-20

I want to make a component in the front page that displays list of vehicles with navigation buttons that shows list of the selected button.

Is there a better way I could write this code below because I want the list of categories to be much longer? Or are there other methods I can use other than useState & useEffect? I'm using Next.js

const Vehicles = () => {

  const [selectedCategory, setSelectedCategory] = useState("cars")

  const [cars, setCars] = useState(true)
  const [bikes, setBikes] = useState(false)
  const [motorcycles, setMotorcyles] = useState(false)
  const [scooters, setScooters] = useState(false)

  useEffect(() => {
    if (selectedCategory === "cars") {
      setCars(true)
      setBikes(false)
      setMotorcyles(false)
      setScooter(false)
    }
    if (selectedCategory === "bikes") {
      setBikes(true)
      setCars(false)
      setMotorcyles(false)
      setScooters(false)
    }
    if (selectedCategory === "motorcycles") {
      setMotorcyles(true)
      setCars(false)
      setBikes(false)
      setScooters(false)
    }
    if (selectedCategory === "scooters") {
      setScooters(true)
      setCars(false)
      setBikes(false)
      setMotorcyles(false)
    }
  }, [selectedCategory])
  
  return (
    <div>
      <div>
        <button onClick={() => setSelectedCategory("cars")}> Cars </button>
        <button onClick={() => setSelectedCategory("bikes")}> Bikes </button>
        <button onClick={() => setSelectedCategory("motorcycles")}> Motorcycles </button>
        <button onClick={() => setSelectedCategory("scooters")}> Scooters </button>
      </div>

      {cars && (
        <div>
          <Cars />
        </div>
      )}

      {bikes && (
        <div>
          <Bikes />
        </div>
      )}

      {motorcycles && (
        <div>
          <Motorcycles />
        </div>
      )}

      {scooters && (
        <div>
          <Scooters />
        </div>
      )}
    </div>
  );
};

export default Vehicles;

CodePudding user response:

These things like abstraction and code refactor tend to differ from person to person. But what I would generally prefer is something between abstraction and readability. Since readability is much more important I would go along this way

const allCategory = {
    cars: 0,
    bikes: 1,
    motorcycles: 2,
    scooters: 3
}

const Vehicles = () => {
    // set cars as default category. If you don't want it change it to be any integer before 0
    const [category, setCategory] = useState(allCategory.cars)

    return (
        <div>
            <div>
                <button onClick={() => setCategory(allCategory.cars)}> Cars </button>
                <button onClick={() => setCategory(allCategory.bikes)}> Bikes </button>
                <button onClick={() => setCategory(allCategory.motorcycles)}> Motorcycles </button>
                <button onClick={() => setCategory(allCategory.scooters)}> Scooters </button>
            </div>

            <div>
                {category === allCategory.cars && <Cars />}
                {category === allCategory.bikes && <Bikes />}
                {category === allCategory.motorcycles && <Motorcycles />}
                {category === allCategory.scooters && <Scooters />}
            </div>

        </div>
    );
};

export default Vehicles;

If you want to go absolutely crazy. You can decrease this to be in about 4-5 lines in return statement. But I prefer this to be much cleaner

CodePudding user response:

I think you could do something more like

const Vehicles = () => {
 const [selectedCategory, setSelectedCategory] = useState("cars")
 const renderCat = (category) =>{
   switch(category){
     case "cars":
       return <Cars />
     //etc...
   }
 }

  return (
    <div>
      <div>
        <button onClick={() => setSelectedCategory("cars")}> Cars </button>
        <button onClick={() => setSelectedCategory("bikes")}> Bikes </button>
        <button onClick={() => setSelectedCategory("motorcycles")}> Motorcycles </button>
        <button onClick={() => setSelectedCategory("scooters")}> Scooters </button>
      </div>
        <div>
          {renderCat(selectedCategory)}
        </div>
      </div>
  );
};

export default Vehicles;

CodePudding user response:

You could do like this:

const categories = [
  {
    name: "cars",
    title: "Cars",
    component: Cars
  },
  {
    name: "bikes",
    title: "Bikes",
    component: Bikes
  },
  {
    name: "motorcyles",
    title: "Motorcyles",
    component: Motorcyles
  },
  {
    name: "scooters",
    title: "Scooters",
    component: Scooters
  }
];

const Vehicles = () => {
  const [selectedCategory, setSelectedCategory] = useState("cars")
  
  return (
    <div>
      <div>
        {categories.map(({ name, title }) => (
          <button onClick={() => setSelectedCategory(name)}>
            {title}
          </button>
        ))}
      </div>

      {categories.map(({ component: Component, name }) => {
        if(selectedCategory !== name) return;

        return (
          <div>
            <Component />
          </div>
        );
      })}
    </div>
  );
};

export default Vehicles;

The category objects can be different depending on what you want to display. Having both name and title is not essential, it's just an example.

  • Related