Skip to content

v1.14.0

Choose a tag to compare

@edmundhung edmundhung released this 01 Dec 22:07
· 14 commits to main since this release
5f30e77

Breaking Changes (Future APIs)

  • The intendedValue option in the report helper has been renamed to value and now works as the defaultValue when resetting the form. Previously, this option was ignored when resetting and the form would always reset to the default value. You can now use the value option to update or reset forms to a specific value. (#1079)

    // Update form to a specific value after submission
    return {
      result: report(submission, {
        value: updatedValue,
      }),
    };
    
    // Reset form to a specific value after submission
    return {
      result: report(submission, {
        reset: true,
        value: defaultValue,
      }),
    };
  • parseSubmission now strips empty values by default. This makes it easier to work with schemas directly (without coerceFormValue) since you no longer need extra validation like .min(1) for required fields. You can set stripEmptyValues: false to preserve empty values if needed. (#1110)

    const formData = new FormData();
    // Empty text input
    formData.append('name', '');
    // Empty file input
    formData.append('files[]', new File([], ''));
    parseSubmission(formData);
    // { payload: {} }
    parseSubmission(formData, { stripEmptyValues: false });
    // { payload: { name: '', files: [new File([], '')] } }

What's Changed

  • Schema-first future useForm hook with improved type inference (#1106)

    The schema option is now promoted to the first argument of useForm for better type inference:

    // Before: schema in options
    const { form, fields } = useForm({
      schema: mySchema,
      onSubmit(event, { value }) {
        // value type inference could be inconsistent
      },
    });
    
    // After: schema as first argument
    const { form, fields } = useForm(mySchema, {
      onSubmit(event, { value }) {
        // value is fully typed based on your schema
      },
    });
    • onValidate is now required when not using a schema
    • Either onSubmit or lastResult must be provided (Relaxed the type to allow both to be optional in v1.14.1)

    The old API with schema in options still works but is now deprecated. It will be removed in the next minor release.

  • Fixed parseSubmission array handling for entries ending with []. Previously, when multiple form entries had the same name ending with [] (e.g., todos[]), all items were incorrectly pushed as a single nested array element. Now they are correctly spread as individual array items. (#1108)

    const formData = new FormData();
    formData.append('todos[]', 'Buy milk');
    formData.append('todos[]', 'Walk dog');
    formData.append('todos[]', 'Write tests');
    
    parseSubmission(formData);
    // Before (incorrect): { todos: [['Buy milk', 'Walk dog', 'Write tests']] }
    
    // After (correct): { todos: ['Buy milk', 'Walk dog', 'Write tests'] }

Improvements

  • You can now import from @conform-to/zod/v3 if you need to work with v3 schema using zod v4. (Thanks @kesoji - #1090)
  • Fixed type inference for getFieldset() with interface declarations (#1097)
  • Moved lastResult logic from an effect to the render phase. Your form component may now render twice within a single lifecycle when needed, but state updates that previously spanned two separate lifecycles now complete in one. (#1103)
  • Improved FormOptions and ValidationAttributes types compatibility with exactOptionalPropertyTypes setting in tsconfig. (#1105)

Full Changelog: v1.13.3...v1.14.0