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.