Skip to content

Commit 7fe9882

Browse files
committed
chore: add changeset
1 parent 185a536 commit 7fe9882

1 file changed

Lines changed: 135 additions & 0 deletions

File tree

.changeset/quiet-heads-heal.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
"@bigcommerce/catalyst-core": patch
3+
---
4+
5+
Refactor DynamicForm actions to decouple fields and passwordComplexity from state, passing them as separate arguments instead. This reduces state payload size by removing fields from state objects and stripping options from fields before passing them to actions (options are only needed for rendering, not processing). All form actions now accept a `DynamicFormActionArgs` object as the first parameter containing fields and optional passwordComplexity, followed by the previous state and formData.
6+
7+
## Migration steps
8+
9+
### Step 1: Changes to DynamicForm component
10+
11+
The `DynamicForm` component and related utilities have been updated to support the new action signature pattern:
12+
13+
**`core/vibes/soul/form/dynamic-form/index.tsx`**:
14+
- Added `DynamicFormActionArgs<F>` interface that contains `fields` and optional `passwordComplexity`
15+
- Updated `DynamicFormAction<F>` type to accept `DynamicFormActionArgs<F>` as the first parameter
16+
- Removed `fields` and `passwordComplexity` from the `State` interface
17+
- Added automatic removal of `options` from fields before passing to actions (options are only needed for rendering)
18+
- Updated action binding to use `action.bind(null, { fields: fieldsWithoutOptions, passwordComplexity })`
19+
20+
**`core/vibes/soul/form/dynamic-form/utils.ts`** (new file):
21+
- Added `removeOptionsFromFields()` utility function that strips the `options` property from field definitions before passing them to actions, reducing the state payload size
22+
23+
```diff
24+
+ export interface DynamicFormActionArgs<F extends Field> {
25+
+ fields: Array<F | FieldGroup<F>>;
26+
+ passwordComplexity?: PasswordComplexitySettings | null;
27+
+ }
28+
+
29+
+ type Action<F extends Field, S, P> = (
30+
+ args: DynamicFormActionArgs<F>,
31+
+ state: Awaited<S>,
32+
+ payload: P,
33+
+ ) => S | Promise<S>;
34+
+
35+
interface State {
36+
lastResult: SubmissionResult | null;
37+
- fields: Array<F | FieldGroup<F>>;
38+
- passwordComplexity?: PasswordComplexitySettings | null;
39+
}
40+
```
41+
42+
### Step 2: Update DynamicForm action signatures
43+
44+
All form actions that use `DynamicForm` must be updated to accept `DynamicFormActionArgs<F>` as the first parameter instead of including fields in the state.
45+
46+
Update your form action function signature:
47+
48+
```diff
49+
+ import { DynamicFormActionArgs } from '@/vibes/soul/form/dynamic-form';
50+
import { Field, FieldGroup, schema } from '@/vibes/soul/form/dynamic-form/schema';
51+
52+
- export async function myFormAction<F extends Field>(
53+
- prevState: {
54+
- lastResult: SubmissionResult | null;
55+
- fields: Array<F | FieldGroup<F>>;
56+
- passwordComplexity?: PasswordComplexitySettings | null;
57+
- },
58+
- formData: FormData,
59+
- ) {
60+
+ export async function myFormAction<F extends Field>(
61+
+ { fields, passwordComplexity }: DynamicFormActionArgs<F>,
62+
+ _prevState: {
63+
+ lastResult: SubmissionResult | null;
64+
+ },
65+
+ formData: FormData,
66+
+ ) {
67+
```
68+
69+
### Step 2: Remove fields and passwordComplexity from state interfaces
70+
71+
Update state interfaces to remove fields and passwordComplexity properties:
72+
73+
```diff
74+
interface State {
75+
lastResult: SubmissionResult | null;
76+
- fields: Array<Field | FieldGroup<Field>>;
77+
- passwordComplexity?: PasswordComplexitySettings | null;
78+
}
79+
```
80+
81+
### Step 3: Update action implementations
82+
83+
Remove references to `prevState.fields` and `prevState.passwordComplexity` in action implementations:
84+
85+
```diff
86+
const submission = parseWithZod(formData, {
87+
- schema: schema(prevState.fields, prevState.passwordComplexity),
88+
+ schema: schema(fields, passwordComplexity),
89+
});
90+
91+
if (submission.status !== 'success') {
92+
return {
93+
lastResult: submission.reply(),
94+
- fields: prevState.fields,
95+
- passwordComplexity: prevState.passwordComplexity,
96+
};
97+
}
98+
```
99+
100+
### Step 4: Update action calls in components
101+
102+
For actions used with `AddressListSection`, update the action signature to accept fields as the first parameter:
103+
104+
```diff
105+
- export async function addressAction(
106+
- prevState: Awaited<State>,
107+
- formData: FormData,
108+
- ): Promise<State> {
109+
+ export async function addressAction(
110+
+ fields: Array<Field | FieldGroup<Field>>,
111+
+ prevState: Awaited<State>,
112+
+ formData: FormData,
113+
+ ): Promise<State> {
114+
```
115+
116+
### Step 5: Update DynamicForm usage
117+
118+
No changes needed to `DynamicForm` component usage. The component automatically handles binding fields and passwordComplexity to actions. The `DynamicForm` component now:
119+
- Automatically removes options from fields before passing them to actions (reducing payload size)
120+
- Binds fields and passwordComplexity to the action using `action.bind()`
121+
- Maintains the same props interface, so existing usage continues to work
122+
123+
### Affected files
124+
125+
The following files were updated in this refactor:
126+
- `core/vibes/soul/form/dynamic-form/index.tsx` - Added `DynamicFormActionArgs` type and updated action binding
127+
- `core/vibes/soul/form/dynamic-form/utils.ts` - Added `removeOptionsFromFields` utility function
128+
- `core/app/[locale]/(default)/(auth)/register/_actions/register-customer.ts`
129+
- `core/app/[locale]/(default)/account/addresses/_actions/address-action.ts`
130+
- `core/app/[locale]/(default)/account/addresses/_actions/create-address.ts`
131+
- `core/app/[locale]/(default)/account/addresses/_actions/update-address.ts`
132+
- `core/app/[locale]/(default)/account/addresses/_actions/delete-address.ts`
133+
- `core/app/[locale]/(default)/gift-certificates/purchase/_actions/add-to-cart.tsx`
134+
- `core/app/[locale]/(default)/webpages/[id]/contact/_actions/submit-contact-form.ts`
135+
- `core/vibes/soul/sections/address-list-section/index.tsx`

0 commit comments

Comments
 (0)