Conditional dropdowns with react-final-form and react-select using parse and format

618 views Asked by At

This is a follow-up question to several similar questions, but the solution found (<PickOptions /> component by Erik Rasmussen) doesn't seem to work for select options manipulated by parse and format.

I want to "flatten" the options objects into just their value when storing in the form state (and change them back into option objects for rendering with react-select), so I did the following:

const SelectAdapter = ({ input, ...rest }) => (
  <Select {...input} {...rest} searchable />
);

const options = [
  { value: "two-a", label: "Two A" },
  { value: "two-b", label: "Two B" }
];
<Field
  name={fieldName}
  component={SelectAdapter}
  options={options}
  parse={(formattedOption) => formattedOption ? formattedOption.value : undefined}
  format={(parsedValue) => options.find((option) => option.value === parsedValue)}
/>

And changed one line in PickOptions like so:

-const aValue = aField.input.value.value;
+const aValue = aField.input.value;

Now PickOptions seems to properly clear the value of the child/dependent select field as far as react-final-form state/values are concerned, but it still renders the old value in the select field and I cannot figure out why. Any help would be most appreciated! Thanks in advance.

CodeSandbox demonstrating the problem: choose an option in the first dropdown, then choose an option in the second dropdown. Next, change the first dropdown to the other option. It should clear the second dropdown (you'll notice it clears the actual value in the form, in the values printed below the inputs, but leaves the old label text of the previously selected option in the second/child dropdown). You may also notice the Reset button empties the form values internally but does not clear the inputs. Same root cause, I'm assuming.

(edit) Super Hacky Workaround?

const SelectAdapter = ({ input, ...rest }) => {
  const [hack, setHack] = React.useState(0);

  React.useEffect(() => {
    if (rest.options) setHack((hack) => hack + 1);
  }, [rest.options]);

  return <Select key={hack} {...input} {...rest} searchable />;
};
1

There are 1 answers

3
Erik R. On

I'm not sure. If you console.log() the options when rendering childOption, they do change. So maybe react-select is ignoring changes to the options prop? Doesn't seem to be a problem with RFF, from what I can tell.