Skip to content

Releases: edmundhung/conform

v1.7.0

13 Jun 14:11
3841a8c

Choose a tag to compare

What's changed

The future export and useControl hook

We’ve introduced the first API under the new future export: useControl.

The future export is a new entry point for previewing upcoming features that may evolve before being stabilized in a future major version. If you haven’t seen it yet, check out our announcement for context.

The first experimental API is useControl — a new hook that helps you integrate custom inputs with Conform. Compared to useInputControl, it offers a more flexible setup with better support for multi-select, file inputs, and checkbox groups.

We’ve documented it in detail:

Give it a try — and let us know what you think!

New field metadata for default values

Field metadata now includes three new properties:

  • defaultValue (string | undefined)
  • defaultChecked (boolean | undefined)
  • defaultOptions (string[] | undefined)
const { fields } = useForm({
  defaultValue: {
    username: 'edmundhung',
    tags: ['react', 'forms'],
    subscribe: true,
  }
});

fields.username.defaultValue; // 'edmundhung'
fields.tags.defaultOptions;   // ['react', 'forms']
fields.subscribe.defaultChecked; // true

These values are automatically derived from your form’s defaultValue, making it easier to connect each field with useControl and wire up individual input elements.

Full Changelog: v1.6.0...v1.7.0

v1.6.0

22 May 22:46
0c00a13

Choose a tag to compare

What's Changed

  • Added Zod v4 support in #902

    You can now use our Zod helpers with any Zod v4 schema by importing from the new module export @conform-to/zod/v4:

import {
  parseWithZod,
  getZodConstraint,
} from '@conform-to/zod/v4';

Special thanks to @chimame for championing this upgrade and making Zod v4 compatibility possible!

Full Changelog: v1.5.1...v1.6.0

v1.5.1

15 May 10:42
7fd9c1d

Choose a tag to compare

What's Changed

  • fix: useInputControl() should not return an array value when form.update() is called with a single value (#935)

Full Changelog: v1.5.0...v1.5.1

v1.5.0

05 May 23:02
936fb44

Choose a tag to compare

What's Changed

  • feat(conform-zod): Set empty object when zodDiscriminatedUnion is specified. by @taku-hatano in #909
  • feat(conform-zod): Add support auto type coercion with z.literal for boolean, number, and bigint by @elecdeer in #930
  • feat(conform-valibot): Add support auto type coercion with literal for boolean, number, and bigint by @chimame in #931
  • fix(conform-valibot): support nested fields with only checkboxes by @chimame in #911
  • fix(conform-valibot): where undefined value could not be correctly verified when array was defined in nullish or optional schema by @chimame in #917
  • fix(conform-valibot): re-support Valibot config/fallback methods for piped primitive value schemas by @nanto in #925
  • fix(conform-valibot): fix synchronize reference versions by @chimame in #932

Improvements

  • Bumped @conform-to/valibot package version to sync the with the rest of the packages in #929.
  • Added an installation guide in #918. Thanks @chimame
  • Updated docs in #912, . Thanks @lhapaipai!
  • Fixed an issue with the README file missing on the published packages in #927. Thanks @edmundhung

New Contributors

Full Changelog: v1.4.0...v1.5.0

v1.4.0

15 Apr 20:56
1433173

Choose a tag to compare

What's Changed

Form side effect

Previously, Conform heavily relied on the React key prop to update the input value when updating field values with form.update() or resetting the form with form.reset().This was not ideal and have introduced several issues along the way, such as the unexpected onBlur validation behavior caused by React re-mounting the input when the key prop changes and the new warning message with spreading key with getInputProps() in React 19.

In v1.4.0, Conform will run a side effect to update the input value instead. Meaning...

  • Helpers like getInputProps, getSelectProps or getTextareaProps are no longer spreading a key to the input element. If you were seeing the message Warning: A props object containing a "key" prop is being spread into JSX, it should be resolved now.
  • Outstanding issues caused by inputs being unmounted (e.g. #701 and #730) are now fixed

With the need of key props removed, Conform is now able to validate and update the input value as long as a name is provided:

function Example() {
  const [form, fields] = useForm({
    // ...
  });

  return (
    <form id={form.id} onSubmit={form.onSubmit}>
      <input type="text" name={fields.username.name} />
      <input type="password" name={fields.password.name} />
      <button>Submit</button>
    </form>
  );
}

v1.3.0

22 Mar 16:00
077215b

Choose a tag to compare

Hello world! We're finally back after a bit of a break. This release is a bit small, but we hope it's the start of a more regular update schedule moving forward. I'm excited to share that @chimame has joined the team and is prepping our first valibot integration release in #876. We'll be sharing more details about the other changes as well. Thanks for your patience and stay tuned!

Custom coercion

v1.3.0 adds the ability to disable the default auto coercion behavior by setting the disableAutoCoercion option to true in parseWithZod in #871.

function Example() {
  const [form, fields] = useForm({
    onValidate({ formData }) {
      return parseWithZod(formData, {
        schema,
        disableAutoCoercion: true,
      });
    },
  });

  // ...
}

You can then manage how the form value is parsed yourself, or use the new unstable_coerceFormValue helper to coerce form value:

import { parseWithZod, unstable_coerceFormValue as coerceFormValue } from '@conform-to/zod';
import { z } from 'zod';

// Coerce the form value with default behaviour
const schema = coerceFormValue(
  z.object({
    // ...
  })
);

// Coerce the form value with default coercion overrided
const schema = coerceFormValue(
  z.object({
    ref: z.number()
    date: z.date(),
    amount: z.number(),
    confirm: z.boolean(),
  }),
  {
    // Trim the value for all string-based fields
    // e.g. `z.string()`, `z.number()` or `z.boolean()`
    string: (value) => {
      if (typeof value !== 'string') {
         return value;
      }

      const result = value.trim();

      // Treat it as `undefined` if the value is empty
      if (result === '') {
         return undefined;
      }

      return result;
    },

    // Override the default coercion with `z.number()`
    number: (value) => {
      // Pass the value as is if it's not a string
      if (typeof value !== 'string') {
        return value;
      }

      // Trim and remove commas before casting it to number
      return Number(value.trim().replace(/,/g, ''));
    },

    // Disable coercion for `z.boolean()`
    boolean: false,
  },
);

You can also customize coercion for a specific schema by setting the customize option.

import {
  parseWithZod,
  unstable_coerceFormValue as coerceFormValue,
} from '@conform-to/zod';
import { useForm } from '@conform-to/react';
import { z } from 'zod';
import { json } from './schema';

const metadata = z.object({
  number: z.number(),
  confirmed: z.boolean(),
});

const schema = coerceFormValue(
  z.object({
    ref: z.string(),
    metadata,
  }),
  {
    customize(type) {
      // Customize how the `metadata` field value is coerced
      if (type === metadata) {
        return (value) => {
          if (typeof value !== 'string') {
            return value;
          }

          // Parse the value as JSON
          return JSON.parse(value);
        };
      }

      // Return `null` to keep the default behavior
      return null;
    },
  },
);

This helper is currently released with the unstable_ prefix to collect more feedbacks. Lock your version to the patch version range (e.g. ~1.3.0) if you want to use this feature without unexpected changes.

Other Improvements

New Contributors

Full Changelog: v1.2.2...v1.3.0

v1.2.2

19 Sep 22:15
2f2111c

Choose a tag to compare

What's Changed

fix: revert auto field value update (#778)

Revert #729 and #766

The auto field value update feature introduced in v1.2.0 has caused several critical issues with significant user impact. While I appreciate what they accomplished, I’ve realized the current solution isn't robust enough to handle all potential use cases. To minimize the impact on everyone, I believe it's best to revert these changes for now.

Full Changelog: v1.2.1...v1.2.2

v1.2.1

14 Sep 16:12
24105f4

Choose a tag to compare

What's Changed

  • Fixed an issue with Conform overwriting the value of input buttons in #766. In v1.2.0, if you have any input buttons rendered, their value will be likely rewritten to empty string as Conform treats it as normal inputs and tries to update its value based on the default value.

Full Changelog: v1.2.0...v1.2.1

v1.2.0

14 Sep 13:31
db63782

Choose a tag to compare

Embrace the platform

This change is reverted in v1.2.2

One of the most critical changes in this release is the auto field value update implemented in #729. Conform now updates input value using the DOM api instead of relying on the key to re-mount the inputs with the new defaultValue. It means:

  • It is no longer required to pass the key (e.g. fields.title.key) to the input elements unless you are rendering a list.
// Before: The minimum setup
<input key={field.title.key} name={fields.title.name} defaultValue={fields.title.defaultValue} />
// Now: the key props is no longer required 
<input name={fields.title.name}  defaultValue={fields.title.defaultValue} />
// Bonus: if the form is not rendered server side, or you don't mind the user experience before JS is loaded...
<input name={fields.title.name} />
  • Helpers like getInputProps, getSelectProps or getTextareaProps are no longer spreading a key to the input element. If you were seeing the message Warning: A props object containing a "key" prop is being spread into JSX, it should be resolved now.
  • Outstanding issues caused by inputs being unmounted (e.g. #701 and #730) are now fixed

Pre-release

Thanks to pkg.pr.new, we are now releasing a preview version on every pull request (#742)

You will find a comment on the PR like this one from pkg.pr.new with each package name listed. If you expand the item, you will see a command to install the pre-release version. If you are not using pnpm, you can swap it with npm install, or just copy the package URL and replace the version in the package.json with it.

We are also shipping a pre-release version on every commit merged to main in the format https://pkg.pr.new/@conform-to/package@commit . For example, if you would like to install the pre-release version of @conform-to/dom and @conform-to/zod up to db63782, you can run:

npm install https://pkg.pr.new/@conform-to/dom@db63782
npm install https://pkg.pr.new/@conform-to/zod@db63782

Other Improvements

  • Improved the types of submission.payload in #706. If you were using Remix with single fetch, the action results should no longer be in type never. Thanks @timvandam!
  • Fixed empty string default value support in #741. Previously, we suggested using .default() to set a fallback value. However, .default() does not work as expected with z.string().default(''). This issue has now been resolved, but keep in mind that the default value is still subject to validation errors. For more predictable results, we recommend using .transform(value => value ?? defaultValue) instead.
  • Implement zod object coercion in #733. Conform should support nested fields with only checkboxes now.
  • Added bigint coercion support with zod in #726. Thanks @lifeiscontent!
  • Improved the types of the default value in #719. As FormValue should never be null. Thanks @aaronadamsCA!
  • Added a multiple select example with shadcn-ui in #753. Thanks @pwli0755!
  • Improved the shadcn-ui Switch Component example to use control.value in #721. Thanks @reborn2135!
  • Fixed typo in parseWithYup.md and FormProvider.md in #708, #751. Thanks @uttk, @felixyeboah!
  • Improved the ja docs messages in #709, #710, #711, #712. Thanks @k70suK3-k06a7ash1!
  • Explained the usage of allErrors with checkbox group in #735.

New Contributors

Full Changelog: v1.1.5...v1.2.0

v1.1.5

17 Jun 21:03
650c3d7

Choose a tag to compare

Improvements

  • Fixed an issue with unstable_useControl not resetting the value of the registered input on form reset (#674)

Full Changelog: v1.1.4...v1.1.5