resolvers icon indicating copy to clipboard operation
resolvers copied to clipboard

AJV Resolver - When ajv schema contains `default` for certain properties, `getValues()` returns the form data with properties overwritten

Open javier-brenes-zen opened this issue 2 years ago • 0 comments

Describe the bug I have an ajv schema that contains default definitions for some properties. Then when calling useForm I pass values with populated data that I retrieved from DB, I can see the data being rendered in UI. When I call getValues function to get the form data without touching any of the inputs, the returned data by getValues no longer contains the initial info provided via values but instead those properties that had a default attribute in the ajv schema are overwritten.

To Reproduce Steps to reproduce the behavior:

  1. Define an ajv schema like this:
const ajvSchema = {
  type: 'object',
  properties: {
    user: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          default: 'Camilo',
        },
        lastName: {
          type: 'string',
          default: 'A random lastName',
        },
        email: {
          type: 'string',
          default: '[email protected]',
        },
      },
    },
  },
  required: ['user'],
};
  1. When calling useForm on your component make sure you add values:
 const {
    control,
    getValues,
    trigger,
    formState: { errors, isValid },
  } = useForm({
    values: { user: { name: 'Javier', lastName: 'Brenes', email: '[email protected]' } },
    shouldUnregister: true,
    resolver: ajvResolver(ajvSchema, {
      useDefaults: true,
      removeAdditional: true,
    }),
  });
  1. Render your inputs using Controller
<div style={{ marginBottom: '10px' }}>
        <label>First Name: </label>
        <Controller
          control={control}
          name="user.name"
          render={({ field }) => (
            <input onChange={field.onChange} value={field.value} />
          )}
        />
      </div>
      <div style={{ marginBottom: '10px' }}>
        <label>Last Name: </label>
        <Controller
          control={control}
          name="user.lastName"
          render={({ field }) => (
            <input
              onChange={handleOnChange(field.onChange)}
              value={field.value}
            />
          )}
        />
      </div>
      <div style={{ marginBottom: '10px' }}>
        <label>email: </label>
        <Controller
          control={control}
          name="user.email"
          render={({ field }) => (
            <input
              onChange={handleOnChange(field.onChange)}
              value={field.value}
            />
          )}
        />
      </div>
  1. Call getValues() without modifying any of the inputs, you will get lastName and email with their default values from the ajv schema, this is wrong because those properties contain info that was passed to the values property in UseForm.

This is what I am getting:

{ "user": { "name": "Javier", "lastName": "A random lastName", "email": "[email protected]" } }

This is what I want to get since I didn't touch any input, and values where set up.

{ user: { name: 'Javier', lastName: 'Brenes', email: '[email protected]' } },

Codesandbox link (Required) https://stackblitz.com/edit/stackblitz-starters-purvrb?file=src%2FApp.js

Expected behavior getValues should return the set up data via values if none of the inputs were touched. default values in ajv schema should only be used when the property is not part of the form data already.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS] MAC os
  • Browser [e.g. chrome, safari] Chrome, safari, firefox
  • Version [e.g. 22]

Additional context Add any other context about the problem here.

javier-brenes-zen avatar Nov 15 '23 18:11 javier-brenes-zen