Topic: React Multiselect resets immediately after clicking check box (only if setting state)

waiiki free asked 2 years ago


Expected behavior

So I'm trying to allow my users to select from multiple roles they would like. I'd like to be able to store these roles in a state, so that I can submit them as part of another form in the same component all at once. However when I attempt to set state (in this case with setSelectedRoles, which is string[]) the multiselect quickly flicks off all the toggle options. The console log there correctly logs the selected options, but the selections are toggled off the state is also cleared.

            const [selectedRoles, setSelectedRoles] = useState<string[]>([]); //above the return block

 <MDBSelect
                  data={allRoles.map((value: RoleDTO, index: number) => {
                    return { text: value.name as string, value: index };
                  })}
                  multiple
                  label="Roles"
                  onValueChange={(e) => {
                    if (e instanceof Array){
                      setSelectedRoles(e.map((r) => r.text!));
                    }
                    console.log(JSON.stringify(selectedRoles));
                  }}
                />

Note that the options correctly stay checked if in the onValueChanged event I do not change state, however I need to capture the selected options somehow


Krzysztof Wilk staff answered 2 years ago


Hi!

You should wrap your data in the useMemo hook to memoize its value. So you can do:

const selectData = useMemo(() => selectedRoles.map((value: RoleDTO, index: number) =>{ return { text: value.name as string, value: index };}), [selectedRoles])

to prevent the Select component from rendering and pass this memoized variable to data property :)


waiiki free commented 2 years ago

That seems to have worked for the updating of the component. However logging "selectedRoles" now only returns an empty array.

const [selectedRoles, setSelectedRoles] = useState<string[]>([]);
let selectData = useMemo(() => 
allRoles.map((value: RoleDTO, index: number) =>{ return { text: value.name as string, value: index };}), [selectedRoles])

data={selectData} multiple label="Roles" onValueChange={(e) => {

                    console.log(JSON.stringify(selectedRoles));
                  }}

I have also tried replacing [selectedRoles] with [setSelectedRoles] and the same.

Is there another place I should be retrieving the selected role data from?

Edit: Removing: if (e instanceof Array){ setSelectedRoles(e.map((r) => r.text!)); } from onValueChanged is what allows the visuals of the component to work. However if I KEEP this line in here, the console.log correctly shows the clicked values but does NOT keep the component visuals updated. Everything is also immediately reset, including the selectedRoles state (even with memo) Its the same as the original post.


waiiki free commented 2 years ago

Here is a pastebin of the full component. The MultiSelect is near the bottom

https://pastebin.com/fmLxBC6s



Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Answered

Specification of the issue

  • ForumUser: Free
  • Premium support: No
  • Technology: MDB React
  • MDB Version: MDB5 5.0.0
  • Device: PC
  • Browser: Chrome
  • OS: Windows 10
  • Provided sample code: No
  • Provided link: No