Home > Blockchain >  Is there a better approach to making a list of options in React than this?
Is there a better approach to making a list of options in React than this?

Time:11-15

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

  • Related