data-driven-forms / react-forms

React library for rendering forms.
https://data-driven-forms.org/
Apache License 2.0
298 stars 87 forks source link

Multiselect dropdown with loadOptions doesn't allow selecting #264

Closed skateman closed 4 years ago

skateman commented 4 years ago

If a dropdown is set to multi and the options are loaded through a promise with loadOptions, the component gets re-rendered anytime you select an option. This causes the inability to select anything.

@Hyperkid123

rvsia commented 4 years ago

Cannot reproduce this issue

schema

{
    component: 'select-field',
    name: 'select-field-3',
    label: 'Dropdown 1 multi false simple value',
    loadOptions: () => fetch('https://dog.ceo/api/breeds/list/all').then(data => data.json()).then(data => data.message.hound.map((x) => ({
        label: x,
        value: x,
    }))),
    multi: true,
},

Everything works as it should.

multiselect

Hyperkid123 commented 4 years ago

@skateman does your component have key?

skateman commented 4 years ago

Doesn't work even with a key attribute

skateman commented 4 years ago

I added an empty useEffect with a console.log call and determined that the single select does 3 reloads for an open + select while the multiselect does 6.

Also a strange thing, if I have the field rendered as a single select and select a field, then changing it to multi -> it just works as it should.

Hyperkid123 commented 4 years ago

Does your component have some state management inside of it? I suspect that the is because the state changes create new instance instead of just updating the props.

skateman commented 4 years ago

https://github.com/ManageIQ/manageiq-ui-classic/pull/6506/files#diff-bd0ffa1799410bbea6710e45b1208823

rvsia commented 4 years ago

@Hyperkid123 @skateman so, should we close this issue? This repository doesn't seem to be the right place to discuss the issue.

Hyperkid123 commented 4 years ago

I will try to reproduce it in clean project

Hyperkid123 commented 4 years ago

@skateman ok so the issue is in the React.cloneElement part which is used when passing children to custom component. Problem is that the component is re-mounted not updated which causes the value and promise to reset.

To fix it you have two options:

 <FieldProvider {...rest} render={props => <RawTagControl {...props} /> }>

 <FieldProvider {...rest} component={RawTagControl} />

Let us know if this fixes the issue with re-mounting

I am not 100% sure what is the cause, but this worked for me. @rvsia We should add to the docs that using the component prop is the n.o 1 option and render is the n.o 2.

skateman commented 4 years ago

It works, thank you!