Woodchuck
Woodchuck

Reputation: 4414

React-Admin ReferenceInput no longer triggers onChange

I'm using React-Admin and have a SimpleForm where I want to trigger some generic action any time any of form fields are changed, including a ReferenceInput selection field.

I'm upgrading from React-Admin version 2.9 to 4.x. In the former version I had an onChange control on a SimpleForm and it triggered when any form field was changed, including ReferenceInput fields. In the new version, changing the ReferenceInput dropdown selection no longer triggers the onChange event.

Why is that? And is there some way to get it working again?

...
import { 
  Create, SimpleForm, TextInput, ReferenceInput, SelectInput
} from 'react-admin';

const doSomething = () => {
    // something
};

const ItemCreate = ({ dataProvider, ...props }) => (
  <>
    <Create title="Create Class" {...props}>

      <SimpleForm onChange={doSomething}>

        <TextInput source="name" label="Name"/>
        
        <!-- no longer triggers the onChange event (doSomething) -->
        <ReferenceInput label="Item" source="item" reference="items">
          <SelectInput optionText={(choice) => `${choice.itemName}`} />
        </ReferenceInput>

      </SimpleForm>

    </Create>
  </>

Upvotes: 1

Views: 1002

Answers (3)

Woodchuck
Woodchuck

Reputation: 4414

I resolved this using react-hook-form's useFormContext(), as suggested by @MaxAlex.

I was able to avoid using a pseudo-component. I basically did the following:

  • remove onChange, as it no longer seems to work with React-Admin's ReferenceInput
  • move the input component outside of the SimpleForm (when I put useFormContext() directly into the component that contains SimpleForm it returns null)
  • inside a useEffect in that separate input component, use useFormContext, and/or other react-hook-form functionality (e.g., dirtyFields or useWatch) to monitor form field changes and take action based on that

Example:

...
import { 
  Create, SimpleForm, TextInput, ReferenceInput, SelectInput
} from 'react-admin';
import { useFormContext } from 'react-hook-form';

const MyInput = () => {
  const formContext = useFormContext();
  useEffect(() => {
    const { dirtyFields } = formContext.formState;

    // if the user changes fieldA, modify fieldB
    if (
      Object.keys(dirtyFields).includes('fieldA')
    ) {
      formContext.setValue('fieldB', 1);
    }
  });
  return (
    <ReferenceInput label="Form Field B" source="fieldB" reference="items">
      <SelectInput optionText={(choice) => `${choice.itemName}`} />
    </ReferenceInput>
  );
};

...
const ItemCreate = () => {
  return (
    <Create>
      <SimpleForm>
        // other form fields, including fieldA
        <MyInput />
      </SimpleForm>
    </Create>
  );
};
...

I've found that, in addition to addressing the issue of onChange no longer working on my ReferenceInput field, react-hook-form seems to provide more granular control than onChange did.

Upvotes: 0

WiXSL
WiXSL

Reputation: 709

You can use the validate prop instead of onChange in the SimpleForm.

And please, read the Form validation section in the docs, this should help you as well.

Upvotes: 0

MaxAlex
MaxAlex

Reputation: 3319

Somewhere inside the form you can call:

import { useFormContext } from 'react-hook-form'
...
const { watch } = useFormContext()
watch((data, { name, type }) => console.log(data, name, type))

https://react-hook-form.com/api/useformcontext

https://react-hook-form.com/api/useform/watch

Upvotes: 1

Related Questions