'REACT-Retrieve the selected dish options ids from a react-seelct dropdown and send them to the backend

How can I retrieve the dishId selected from my options react - select that shows me thedishType in order to send them my parent component FormRender and to the backend.

My first dropdown shows me: Menu1, Menu2...

My second one: type2...

So if I click ontype4, how can I store the related dishId(here = 4). I can click on several values i.e: type2 andtype3.

How do I keep the dish ids i.e : 2 and 3 and send them to my FormRender parent

Menus(first page of my multi - step form):

export default function Menus() {
    const [selectionMenus, setSelectionMenus] = useState({});
    const [selectionDishes, setSelectionDishes] = useState({});
    const [menus, setMenus] = useState([])
    const [date, setDate] = useState('')

    useEffect(() => {
        axios
            .post(url)
            .then((res) => {
                console.log(res);
                setMenus(res.data.menus);
            })
            .catch((err) => {
                console.log(err);
            });
    }, []);

    const names = menus?.map(item => {
        return {
            label: item.menuId,
            value: item.name
        }
    })

    const types = menus?.flatMap(item => {
        return item.dishes.map(d => ({
            label: d.dishId,
            value: d.dishType
        }))
    })
    const handle = (e) => {
        if (e?.target?.id === undefined) return setInfo(e);
        if (e?.target?.id === undefined) return setSelectionMenus(e);
        if (e?.target?.id === undefined) return setSelectionDishes(e);
        switch (e.target.id) {
            case "date":
                setDate(e.target.value);
                break;            
                ...
            default:
}
    }
};
return (
    <>
        <form>
            <div>My menus</div>
            <label>
                Dishes :
                <Dropdown
                    options={names}
                    value={selectionMenus}
                    setValue={setSelectionMenus}
                    isMulti={true}
                />
            </label>
            <label>
                <Dropdown
                    options={types}
                    value={selectionDishes}
                    setValue={setSelectionDishes}
                    isMulti={true}
                />
            </label>
            <label>
                Date:
                <div>
                    <input
                        type="date"
                        name='date'
                        value={date}
                        onChange={handle}
                        id="date"
                    />
                </div>
            </label>
            ...
        </form>
        <div>
            <button onClick={() => nextPage({ selectionDishes, selectionMenus, date })}>Next</button>
        </div>
    </>
);
}

Here the parent Component FormRender that is supposed to retrieve the values of all dishId selected and send them to the backend:

export default function FormRender() {
    const [currentStep, setCurrentStep] = useState(0);
    const [info, setInfo] = useState();
    const [user, setUser] = useState();
    const headers = ["Menus", "Details", "Final"];
    const steps = [
        <Menus
            nextPage={(menu) => {
                setInfo(menu);
                setCurrentStep((s) => s + 1);
            }}
        />,
        <Details
            backPage={() => setCurrentStep((s) => s - 1)}
            nextPage={setUser}
        />,
        <Final />
    ];
    useEffect(() => {
        if (info === undefined || user === undefined) return;
        const data = {
            date: info.date,
            id: //list of dishId selected but don't know how to do that??
        };
    }, [info, user]);

    return (
        <div>
            <div>
                <Stepper steps={headers} currentStep={currentStep} />
                <div >{steps[currentStep]}</div>
            </div>
        </div>
    );
}

Dropdown:

export default function Dropdown({ value, setValue, style, options, styleSelect, isMulti = false }) {

    function change(option) {
        setValue(option.value);
    }

    return (
        <div onClick={(e) => e.preventDefault()}>
            {value && isMulti === false ? (
                <Tag
                    selected={value}
                    setSelected={setValue}
                    styleSelect={styleSelect}
                />
            ) : (
                <Select
                    value={value}
                    onChange={change}
                    options={options}
                    isMulti={isMulti}
                />
            )}
        </div>
    );
}

Here my json from my api:

{
    "menus": [
        {
            "menuId": 1,
            "name": "Menu1",
            "Description": "Descritption1",
            "dishes": [
                {
                    "dishId": 2,
                    "dishType": "type2"
                },
                {
                    "dishId": 3,
                    "dishType": "type3"
                },
                {
                    "dishId": 4,
                    "dishType": "type4"
                }
            ]
        },
        ...
    ]
}


Solution 1:[1]

You already store the selected values inside the selectionMenus and selectionDishes states. So, if you want to send them to the parent FormRender component you can instead create those two states inside that component like this:

export default function FormRender() {
 const [selectionMenus, setSelectionMenus] = useState();
 const [selectionDishes, setSelectionDishes] = useState();
 ....
}

Then pass those values to the Menus component:

<Menus
 selectionMenus={selectionMenus}
 setSelectionMenus={setSelectionMenus}
 selectionDishes={selectionDishes}
 setSelectionDishes={setSelectionDishes}
 nextPage={(menu) => {
  setInfo(menu);
  setCurrentStep((s) => s + 1);
 }}
/>

Subsequently, you will have to remove the state from the Menus component and use the one you receive from props:

export default function Menus({ selectionMenus, setSelectionMenus, selectionDishes, setSelectionDishes }) {
 /*const [selectionMenus, setSelectionMenus] = useState({}); //remove this line
 const [selectionDishes, setSelectionDishes] = useState({});*/ //remove this line
...
}

Finally, you can use inside your useEffect hook the two states and map them to only get the selected ids:

useEffect(() => {
 // ... other logic you had

 if(selectionDishes?.length && selectionMenus?.length){
  const data = {
    date: info.date,
    id: selectionDishes.map(d => d.dishId),
    idMenus: selectionMenus.map(m => m.menuId)
  };
 }
}, [info, user, selectionMenus, selectionDishes]);

Solution 2:[2]

react-select has options to format the component:

getOptionLabel: option => string => used to format the label or how to present the options in the UI,

getOptionValue: option => any => used to tell the component what's the actual value of each option, here you can return just the id

isOptionSelected: option => boolean => used to know what option is currently selected

onChange: option => void => do whatever you want after the input state has changed

value => any => if you customize the above functions you may want to handle manually the value

Hope it helps you

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Osmanys Fuentes-Lombá