marmelab / react-admin

A frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design
http://marmelab.com/react-admin
MIT License
24.89k stars 5.24k forks source link

Programmatically changing the value of an input not working #7791

Closed jogibs closed 2 years ago

jogibs commented 2 years ago

Hey there! I'm having an issue with programmatically changing the value of an input, but none of the options seem to work. See below:

What you were expecting: The value should be applied to the input

What happened instead: The value isn't applied to the input

Related code:

import {
  Create,
  SimpleForm,
  required,
  TextInput,
  CreateProps,
  SelectInput,
  SelectInputProps,
  TextInputProps,
} from 'react-admin';
import { useWatch } from 'react-hook-form';

const commands = [{ id: 'test', name: 'Executes the test command', command: 'yarn test' }];

export const CommandCreateTypeInput = (props: SelectInputProps) => {
  // I've even have had an onChange={(event) => { setValue('command', event.target.value) }}
  // but that didn't work either
  return <SelectInput choices={commands} fullWidth {...props} />;
};

export const CommandCreateCommandInput = (props: TextInputProps) => {
  const type = useWatch({ name: 'type' });
  // const { setValue } = useForm();

  const value = commands.find((command) => {
    return command.id === type;
  })?.command;

  // Doesn't work
  // setValue('command', value);

  // Doesn't work either
  return <TextInput validate={required()} value={value} fullWidth {...props} />;
};

export const CommandCreate = (props: CreateProps) => (
  <Create {...props}>
    <SimpleForm>
      <CommandCreateTypeInput source="type" />
      <CommandCreateCommandInput source="command" />
    </SimpleForm>
  </Create>
);

Environment

fzaninotto commented 2 years ago

Is it possible that you have two versions of react-hook-form in your yarn.lock? I've had this type of problem in the past due do useForm addressing a different version of the form context than the one used by react-admin.

jogibs commented 2 years ago

@fzaninotto Thanks for the quick answer!

Doesn't seem to be the case: CaptureNpmList

EDIT: Also, in /node_modules/react-hook-form/package.json, the version is 7.31.3

fzaninotto commented 2 years ago

OK, then can you please build a reproduction based on the Simple Example Codesandbox?

https://codesandbox.io/s/github/marmelab/react-admin/tree/master/examples/simple

jogibs commented 2 years ago

@fzaninotto

Here we go: https://codesandbox.io/s/clever-danny-rl2uym?file=/src/posts/PostCreate.tsx

slax57 commented 2 years ago

@jogibs I believe you need to use useFormContext instead of useForm. As we can see on the example in the react-hook-form doc, useForm is to declare a new form (which is done internally by react-admin), and useFormContext is a helper to access the form context from within the form.

Here is a working example for your case: https://codesandbox.io/s/zealous-glade-t8cykp?file=/src/posts/PostCreate.tsx

Btw, linking two input fields is documented here: https://marmelab.com/react-admin/Inputs.html#linking-two-inputs

jogibs commented 2 years ago

Thanks!

afilp commented 2 years ago

@jogibs I believe you need to use useFormContext instead of useForm. As we can see on the example in the react-hook-form doc, useForm is to declare a new form (which is done internally by react-admin), and useFormContext is a helper to access the form context from within the form.

Here is a working example for your case: https://codesandbox.io/s/zealous-glade-t8cykp?file=/src/posts/PostCreate.tsx

Btw, linking two input fields is documented here: https://marmelab.com/react-admin/Inputs.html#linking-two-inputs

The link to the working example is not working, we would like to see how to use this.

Thanks!

christiaanwesterbeek commented 2 years ago

@slax57

useForm is to declare a new form (which is done internally by react-admin), and useFormContext is a helper to access the form context from within the form.

This is golden! Will print out on a tile and hang it in my office. Will save me more hours debugging my custom inputs and forms not playing ball with me.