1

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"
                }
            ]
        },
        ...
    ]
}
Zokulko
  • 211
  • 4
  • 25

2 Answers2

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]);
Hakim Abdelcadir
  • 1,231
  • 4
  • 15
  • And the `Next` button in my `Menus`,, do I need to change something too ? – Zokulko Jun 06 '22 at 09:34
  • Just add the prop nextPage in the argument like this export default function Menus({ selectionMenus, setSelectionMenus, selectionDishes, setSelectionDishes, nextPage }) { – Hakim Abdelcadir Jun 06 '22 at 09:46
  • thanks, do you have idea about this [issue](https://stackoverflow.com/questions/72517068/react-how-can-i-display-string-data-from-my-api-with-react-wysiwyg) please ? – Zokulko Jun 06 '22 at 11:38
  • If I solved it please make sure to tick the answer as correct – Hakim Abdelcadir Jun 06 '22 at 11:53
  • Why when I select on a `dishType` option in my dropdown I get in my console.log I got `selectionDishes: undefined` and `setSelectionDishes : ƒ bound dispatchSetState() {}`? – Zokulko Jun 06 '22 at 13:19
-1

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