I am very new to using React, but my gut tells me this concept has come up already and there are better tools or methods of dealing with it than what I used. I want to have a list of buttons to choose from, and when one is clicked, to display that menu and remove the other buttons. My current solution is to have a Options Menu component that has a switch to handle the buttons when they are clicked and exited (code included).
Is this the best approach or is there a better way?
const options = ["Monsters", "Champions", "Dice", "Arena"];
const closeHandler = () => {
setSelected("");
};
switch (selected) {
case "":
return (
<div>
<ul>
{options.map(option =>
<li>
<button onClick={selectionHandler}>{option}</button>
</li>
)}
</ul>
</div>
);
case "Monsters":
return (
<MonsterMenu onClose={closeHandler} />
);
case "Champions":
return (
<ChampionMenu onClose={closeHandler} />
);
case "Dice":
return (
<DiceMenu onClose={closeHandler} />
);
case "Arena":
return (
<ArenaMenu onClose={closeHandler} />
);
CodePudding user response:
Instead of importing and calling 4 different menu components, you could move logic to a general <Menu/>
component, which would handle seperating them by passing the current selected state as a prop.
That would allow you to use a ternary instead of the long switch statement.
Something like:
return (selected ? <Menu type={selected} onClose={closeHandler}/> : /* options */);
If there's already a good bit of similarity and shared code b/w these components, it could reduce redundancy across the board. But there could be a reason to have them as seperate components, in which case the above solution would not be ideal.
CodePudding user response:
Maybe you could:
interface IOption {
id: string;
menu: JSX.Element;
}
function Component() {
const [optionSelected, setOptionSelected] = useState<IOption | null>(null)
const selectionHandler = (option: IOption) => () => {
setOptionSelected(option);
}
const closeHandler = useCallback(() => {
setOptionSelected(null);
}, []);
const options: IOption[] = useMemo([
{id: "Monsters", menu: <MonsterMenu onClose={closeHandler}/> },
{id: "Champions", menu: <ChampionMenu onClose={closeHandler}/> },
{id: "Dice", menu: <DiceMenu onClose={closeHandler}/> },
{id: "Arena", menu: <ArenaMenu onClose={closeHandler}/> },
], [closeHandler]);
return (
<>
{!optionSelected ?
<div>
<ul>
{options.map(option =>
<li key={option.id}>
<button onClick={selectionHandler(option)}>{option.id}</button>
</li>
)}
</ul>
</div> : optionSelected?.menu }
</>
);
}
Pd: I use TypeScript because I Like and I think you can understand better
Why I use useMemo?, because I don't know if your Menu components are going to have more props, or those Menu have heavy logic. To improve performance.
Why I use useCallback?, because ESlint suggests it to me.
Long live ESlint