Skip to content

Commit aef2a34

Browse files
committed
feat: adapt the demo to the new return method.
1 parent f9ebe69 commit aef2a34

File tree

6 files changed

+57
-31
lines changed

6 files changed

+57
-31
lines changed

playground/src/app/(demo)/form/modules/Preserve.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import { useState } from 'react';
44
import { Button, Card, Form, FormField, Input, useForm } from 'soybean-react-ui';
55

6+
import { showToastCode } from './toast';
7+
68
const Preserve = () => {
79
const [form] = useForm();
810

@@ -24,6 +26,12 @@ const Preserve = () => {
2426
<Form
2527
className="w-[480px] max-sm:w-full space-y-4"
2628
form={form}
29+
onFinish={values => {
30+
showToastCode('You submitted the following values', values);
31+
}}
32+
onFinishFailed={errors => {
33+
showToastCode('You failed to submit the form', errors);
34+
}}
2735
>
2836
{show && (
2937
<FormField
@@ -44,16 +52,11 @@ const Preserve = () => {
4452

4553
<div className="flex gap-x-2">
4654
<Button onClick={toggle}>Toggle</Button>
47-
<Button type="submit">Reset</Button>
55+
<Button type="submit">Submit</Button>
56+
<Button onClick={toggleLoad}>Toggle Load</Button>
4857
</div>
4958
</Form>
5059
)}
51-
<Button
52-
className="mt-4"
53-
onClick={toggleLoad}
54-
>
55-
Toggle Load
56-
</Button>
5760
</Card>
5861
);
5962
};

playground/src/app/(demo)/form/modules/Reset.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const Reset = () => {
2424
};
2525

2626
const handleResetUsername = () => {
27-
form.resetFields(['password']);
27+
form.resetFields(['username']);
2828
};
2929

3030
return (

playground/src/app/(demo)/form/modules/UseWatch.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ type Inputs = {
1212
username: string;
1313
};
1414

15+
const EffectWatch = () => {
16+
const values = useWatch<Inputs>();
17+
18+
console.log('values', values);
19+
20+
return null;
21+
};
22+
1523
export default function WatchDemo() {
1624
const [form] = useForm<Inputs>();
1725

@@ -24,7 +32,7 @@ export default function WatchDemo() {
2432
// 3) Watch nested fields
2533
const info = useWatch('info', { form, includeChildren: true });
2634

27-
const { age: NewAge, password: NewPassword, username: NewUsername } = useWatch([], { form });
35+
const { age: NewAge, password: NewPassword, username: NewUsername } = useWatch(form);
2836

2937
useEffect(() => {
3038
showToastCode('NewValues', { NewAge, NewPassword, NewUsername });
@@ -72,6 +80,8 @@ export default function WatchDemo() {
7280
>
7381
<Input placeholder="Enter info.company" />
7482
</FormField>
83+
84+
<EffectWatch />
7585
</Form>
7686

7787
{/* 4) Dynamic rendering */}

primitives/filed-form /src/form-core/createStore.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { assign, isArray, isEqual, isNil, toArray } from 'skyroc-utils';
77

88
import type { FieldEntity } from '../types/field';
99
import type { Callbacks, Store, StoreValue } from '../types/formStore';
10+
import type { Meta } from '../types/shared-types';
1011
import { get } from '../utils/get';
1112
import { set, unset } from '../utils/set';
1213
import type { NamePath, PathTuple } from '../utils/util';
@@ -37,7 +38,7 @@ const matchTrigger = (rule: Rule, trig?: string | string[]) => {
3738
function getValueByNames<T>(source: Map<string, T>, names?: NamePath[]): Record<string, T> {
3839
const keys = names?.length ? names.map(keyOfName) : Array.from(source.keys());
3940

40-
return Object.fromEntries(keys.map(k => [k, source.get(k)!]).filter(([, v]) => v !== undefined));
41+
return Object.fromEntries(keys.map(k => [k, source.get(k)!]));
4142
}
4243

4344
function getFlag(bucket: Set<string>, names?: NamePath[]) {
@@ -596,11 +597,19 @@ class FormStore {
596597
// Fields State (errors/touched/validating/warnings, selectors)
597598
// ------------------------------------------------
598599
private getFields = (names?: NamePath[]) => {
600+
let acc: Record<string, Meta<string, any>> = {};
601+
599602
if (names && names.length !== 0) {
600-
return names.map(name => this.getField(name));
603+
for (const name of names) {
604+
acc = set(acc, keyOfName(name), this.getField(name));
605+
}
606+
} else {
607+
for (const entity of this._fieldEntities) {
608+
acc = set(acc, keyOfName(entity.name), this.getField(entity.name));
609+
}
601610
}
602611

603-
return this._fieldEntities.map(entity => this.getField(entity.name));
612+
return acc;
604613
};
605614

606615
private getField = (name: NamePath) => {
@@ -906,11 +915,11 @@ class FormStore {
906915
if (this._callbacks?.onFieldsChange) {
907916
const fields = this.getFields();
908917

909-
const changedFields = fields.filter(field => {
918+
const changedFields = Object.values(fields).filter(field => {
910919
return nameList.includes(field.name);
911920
});
912921

913-
this._callbacks?.onFieldsChange?.(changedFields, fields);
922+
this._callbacks?.onFieldsChange?.(changedFields, Object.values(fields));
914923
}
915924
};
916925

primitives/filed-form /src/react/hooks/FieldContext.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/* eslint-disable no-bitwise */
33

44
import { createContext, useContext } from 'react';
5-
import type { AllPathsKeys, DeepPartial, PathToDeepType, ShapeFromPaths } from 'skyroc-type-utils';
5+
import type { AllPathsKeys, DeepPartial, KeysToNestedObject, PathToDeepType, ShapeFromPaths } from 'skyroc-type-utils';
66

77
import type { ChangeMask } from '../../form-core/event';
88
import type { Action, Middleware } from '../../form-core/middleware';
@@ -25,7 +25,10 @@ export interface StateOptions<Values = any> {
2525
getFieldError: (name: AllPathsKeys<Values>) => string[];
2626
getFields: (
2727
names?: AllPathsKeys<Values>[]
28-
) => Meta<AllPathsKeys<Values>, PathToDeepType<Values, AllPathsKeys<Values>>>[];
28+
) => KeysToNestedObject<
29+
AllPathsKeys<Values>[],
30+
Meta<AllPathsKeys<Values>, PathToDeepType<Values, AllPathsKeys<Values>>>
31+
>;
2932
getFieldsError: (names?: AllPathsKeys<Values>[]) => Record<AllPathsKeys<Values>, string[]>;
3033
getFieldsTouched: (names?: AllPathsKeys<Values>[]) => boolean;
3134
getFieldsValidated: (names?: AllPathsKeys<Values>[]) => boolean;

primitives/filed-form /src/react/hooks/useFieldState.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
/* eslint-disable react/hook-use-state */
44
import { useEffect, useState } from 'react';
55
import { flushSync } from 'react-dom';
6-
import type { AllPathsKeys, PathToDeepType } from 'skyroc-type-utils';
6+
import type { AllPathsKeys, KeysToNestedObject, PathToDeepType } from 'skyroc-type-utils';
77
import { isArray, isNil, isObject } from 'skyroc-utils';
88

99
import type { SubscribeMaskOptions } from '../../form-core/event';
1010
import { toMask } from '../../form-core/event';
1111
import type { Meta } from '../../types/shared-types';
12+
import { get } from '../../utils/get';
1213

1314
import type { FormInstance, InternalFormInstance } from './FieldContext';
1415
import { useFieldContext } from './FieldContext';
@@ -19,16 +20,12 @@ type UseFormFieldsStateOpts<Values> = {
1920
mask?: SubscribeMaskOptions;
2021
};
2122

22-
export type MetaShape<
23+
export type MetaShapeNested<
2324
Values,
2425
Names extends readonly AllPathsKeys<Values>[] | undefined = undefined
2526
> = Names extends readonly AllPathsKeys<Values>[]
26-
? {
27-
[K in Names[number]]: Meta<K, PathToDeepType<Values, K>>;
28-
}
29-
: {
30-
[K in AllPathsKeys<Values>]: Meta<K, PathToDeepType<Values, K>>;
31-
};
27+
? KeysToNestedObject<Names, Meta<any, any>> // 多字段/全字段 → 嵌套对象
28+
: KeysToNestedObject<AllPathsKeys<Values>[], Meta<any, any>>; // 默认全量
3229

3330
function useFieldState<Values = any, T extends AllPathsKeys<Values> = AllPathsKeys<Values>>(
3431
names: T,
@@ -38,11 +35,13 @@ function useFieldState<Values = any, T extends AllPathsKeys<Values> = AllPathsKe
3835
function useFieldState<Values = any, T extends AllPathsKeys<Values> = AllPathsKeys<Values>>(
3936
names: T[],
4037
opts?: UseFormFieldsStateOpts<Values>
41-
): MetaShape<Values, T[]>;
38+
): MetaShapeNested<Values, T[]>;
4239

43-
function useFieldState<Values = any>(): MetaShape<Values, AllPathsKeys<Values>[]>;
40+
// 无参数:全量嵌套对象
41+
function useFieldState<Values = any>(): MetaShapeNested<Values, AllPathsKeys<Values>[]>;
4442

45-
function useFieldState<Values = any>(form: FormInstance<Values>): MetaShape<Values, AllPathsKeys<Values>[]>;
43+
// form 参数:全量嵌套对象
44+
function useFieldState<Values = any>(form: FormInstance<Values>): MetaShapeNested<Values, AllPathsKeys<Values>[]>;
4645

4746
function useFieldState<Values = any>(
4847
names?: AllPathsKeys<Values> | AllPathsKeys<Values>[] | FormInstance<Values>,
@@ -88,6 +87,8 @@ function useFieldState<Values = any>(
8887
warnings: true
8988
};
9089

90+
const includeChildren = opts?.includeChildren ?? isFormInstance;
91+
9192
const [_, forceUpdate] = useState({});
9293

9394
useEffect(() => {
@@ -97,7 +98,7 @@ function useFieldState<Values = any>(
9798
flushSync(() => forceUpdate({}));
9899
},
99100
{
100-
includeChildren: opts?.includeChildren,
101+
includeChildren,
101102
mask: toMask(mask)
102103
}
103104
);
@@ -106,14 +107,14 @@ function useFieldState<Values = any>(
106107

107108
if (!subscribeNames) {
108109
// names 为空 → 返回 Map 形式
109-
return Object.fromEntries(state.map(item => [item.name, item]));
110+
return state;
110111
}
111112
if (subscribeNames.length === 1) {
112113
// 单字段 → 直接返回该字段的 meta
113-
return state[0];
114+
return get(state, subscribeNames[0]);
114115
}
115116
// 多字段 → 返回对象
116-
return Object.fromEntries(state.map(item => [item.name, item]));
117+
return state;
117118
}
118119

119120
export { useFieldState };

0 commit comments

Comments
 (0)