Skip to content

Commit 19e3ef3

Browse files
committed
fix(Form): 新增store
1 parent 0ac1bd0 commit 19e3ef3

File tree

11 files changed

+211
-70
lines changed

11 files changed

+211
-70
lines changed

example/examples/src/routes/Form/index.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
import React from 'react';
2-
import {Form} from '@uiw/react-native';
3-
import {ComProps} from '../../routes';
4-
5-
export interface FormDemoProps extends ComProps {}
2+
import {Form, Button} from '@uiw/react-native';
3+
import Layout, {Container} from '../../Layout';
4+
const {Body, Footer} = Layout;
65

76
const FormDemo = () => {
87
const items = [{type: 'input', label: 'name'}];
8+
9+
const initialValues = {name: '王滴滴'};
10+
11+
const [form] = Form.useForm();
12+
913
return (
10-
<React.Fragment>
11-
<Form formDatas={items} />
12-
</React.Fragment>
14+
<Container>
15+
<Layout>
16+
<Body>
17+
<Form form={form} formDatas={items} initialValues={initialValues} />
18+
<Button
19+
type="primary"
20+
onPress={() => {
21+
const values = form.getStore();
22+
console.log('values', values);
23+
}}>
24+
默认按钮
25+
</Button>
26+
</Body>
27+
<Footer />
28+
</Layout>
29+
</Container>
1330
);
1431
};
1532

packages/core/src/Form/form.tsx

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
1-
import React, { FC } from 'react';
1+
import React, { useEffect, useRef } from 'react';
22
import FormItems from './formItems';
3-
import { Provider } from './store';
4-
import { FormProps } from './types';
3+
import { Provider } from './hooks/context';
4+
import { FormProps, KeyType } from './types';
5+
import useForm from './hooks/useForm';
56

6-
const Form: FC<FormProps> = (props) => {
7-
const { formDatas } = props;
7+
const Form = <
8+
FormData extends unknown = any,
9+
FieldValue = FormData[keyof FormData],
10+
FieldKey extends KeyType = keyof FormData,
11+
>(
12+
baseProps: FormProps,
13+
) => {
14+
const { formDatas, form, initialValues = {} } = baseProps;
15+
16+
const isMount = useRef<boolean>();
17+
const [formInstance] = useForm<FormData, FieldValue, FieldKey>(form);
18+
19+
if (!isMount.current) {
20+
formInstance.innerSetInitialValues(initialValues);
21+
}
22+
23+
useEffect(() => {
24+
isMount.current = true;
25+
}, []);
26+
27+
const contextProps = {
28+
formInstance: formInstance,
29+
};
830

931
return (
10-
<Provider>
11-
<FormItems formDatas={formDatas} />
32+
<Provider contextProps={contextProps}>
33+
<FormItems formDatas={formDatas} initialValues={initialValues} />
1234
</Provider>
1335
);
1436
};

packages/core/src/Form/formItems.tsx

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,23 @@
1-
import React, { FC } from 'react';
1+
import React, { FC, useContext } from 'react';
22
import { FormProps } from './types';
3-
import { useFormContext } from './store';
3+
import { Context } from './hooks/context';
44
import Input from '../Input';
55

6-
const FormItems: FC<FormProps> = ({ formDatas = [] }) => {
7-
const {
8-
state: { formValues },
9-
dispatch,
10-
} = useFormContext();
6+
const FormItems: FC<FormProps & any> = ({ formDatas = [], initialValues = {} }) => {
7+
const { formInstance } = useContext(Context);
118

12-
const change = (label: string, value: any) => {
13-
dispatch({
14-
formValues: { ...formValues, [label]: value },
15-
});
16-
};
9+
const formValues = formInstance.innerGetStore();
10+
11+
const change = (field: string, value: any) => formInstance?.innerUpdateStore(field, value);
1712

1813
const _render = () => {
19-
return formDatas.map((v: any) => {
14+
return formDatas.map((v: any, i: number) => {
2015
if (v.type === 'input') {
21-
return <Input onChangeText={(value) => change(v.label, value)} />;
16+
return <Input key={i} value={formValues[v.label]} onChangeText={(value) => change(v.label, value)} />;
2217
}
2318
});
2419
};
20+
2521
return <React.Fragment>{_render()}</React.Fragment>;
2622
};
2723

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React, { createContext, useContext, PropsWithChildren, FC, useReducer } from 'react';
2+
import useForm from './useForm';
3+
4+
export interface InitialState {}
5+
6+
export interface CreateContext {
7+
state: Partial<InitialState>;
8+
dispatch: React.Dispatch<InitialState>;
9+
}
10+
11+
export const initialState = {};
12+
13+
const Context = createContext<CreateContext & any>({
14+
state: initialState,
15+
dispatch: () => null,
16+
});
17+
18+
const reducer = (state: Partial<InitialState>, action: Partial<InitialState>) => {
19+
return {
20+
...state,
21+
...action,
22+
};
23+
};
24+
25+
const Provider: FC<PropsWithChildren<any>> = ({ contextProps, children }) => {
26+
const [state, dispatch] = useReducer(reducer, initialState);
27+
return <Context.Provider value={{ ...contextProps, state, dispatch }}>{children}</Context.Provider>;
28+
};
29+
30+
export { Context, reducer, Provider };
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { KeyType } from '../types';
2+
import get from 'lodash/get';
3+
import { cloneDeep, set } from '../utils';
4+
5+
class Store<FormData = any, FieldValue = FormData[keyof FormData], FieldKey extends KeyType = keyof FormData> {
6+
private store: Partial<FormData> = {};
7+
8+
private initialValues: Partial<FormData> = {};
9+
10+
public innerSetInitialValues = (values: any) => {
11+
if (!values) return;
12+
this.initialValues = cloneDeep(values);
13+
Object.keys(values).forEach((field) => {
14+
set(this.store, field, values[field]);
15+
});
16+
};
17+
18+
public innerUpdateStore = (field: string, value?: any) => {
19+
set(this.store, field, value);
20+
};
21+
22+
public innerGetStore = () => {
23+
return this.store;
24+
};
25+
26+
public getFieldValue = (field: FieldKey): FieldValue => {
27+
return cloneDeep(get(this.store, field));
28+
};
29+
30+
public getStore = () => {
31+
return this.store;
32+
};
33+
}
34+
35+
export default Store;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useRef } from 'react';
2+
import { KeyType } from '../types';
3+
import Store from './store';
4+
5+
export function getFormInstance<
6+
FormData = any,
7+
FieldValue = FormData[keyof FormData],
8+
FieldKey extends KeyType = keyof FormData,
9+
>() {
10+
const store = new Store<FormData, FieldValue, FieldKey>();
11+
return {
12+
innerSetInitialValues: store.innerSetInitialValues,
13+
innerGetStore: store.innerGetStore,
14+
innerUpdateStore: store.innerUpdateStore,
15+
getStore: store.getStore,
16+
getFieldValue: store.getFieldValue,
17+
};
18+
}
19+
20+
export default function useForm<
21+
FormData = any,
22+
FieldValue = FormData[keyof FormData],
23+
FieldKey extends KeyType = keyof FormData,
24+
>(form?: any) {
25+
const formRef = useRef(form);
26+
27+
if (!formRef.current) {
28+
if (form) {
29+
formRef.current = form;
30+
} else {
31+
formRef.current = getFormInstance();
32+
}
33+
}
34+
return [formRef.current];
35+
}

packages/core/src/Form/index.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
11
import Form from './form';
2+
import useForm from './hooks/useForm';
23

3-
export default Form;
4+
type RefForm = typeof Form;
5+
6+
export interface FormComponent extends RefForm {
7+
useForm: typeof useForm;
8+
}
9+
10+
const FormComp: FormComponent = Form as FormComponent;
11+
12+
FormComp.useForm = useForm;
13+
14+
export default FormComp;

packages/core/src/Form/store/index.tsx

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
1-
interface FormProps {
1+
import Store from '../hooks/store';
2+
3+
type KeyType = string | number | symbol;
4+
5+
type FormInstance<
6+
FormData = any,
7+
FieldValue = FormData[keyof FormData],
8+
FieldKey extends KeyType = keyof FormData,
9+
> = Pick<
10+
Store<FormData, FieldValue, FieldKey>,
11+
'innerSetInitialValues' | 'innerGetStore' | 'innerUpdateStore' | 'getStore' | 'getFieldValue'
12+
> & {};
13+
14+
interface FormProps<FormData = any, FieldValue = FormData[keyof FormData], FieldKey extends KeyType = keyof FormData> {
215
formDatas?: FormItemsProps[];
16+
form?: FormInstance<FormData, FieldValue, FieldKey>;
17+
initialValues?: any;
318
}
419

520
interface FormItemsProps {
621
label: string;
722
type: string;
823
}
924

10-
export type { FormProps, FormItemsProps };
25+
export type { FormProps, FormItemsProps, KeyType, FormInstance };
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import cloneDeepWith from 'lodash/cloneDeepWith';
2+
import lodashSet from 'lodash/set';
3+
import { isObject, isArray } from './is';
4+
import { PropertyPath } from 'lodash';
5+
6+
export function cloneDeep(value: any) {
7+
// 只有对象才执行拷贝,否则直接返回。 如果是 File,MouseEvent对象,都可以直接返回
8+
return cloneDeepWith(value, (val) => {
9+
if (!isObject(val) && !isArray(val)) {
10+
return val;
11+
}
12+
});
13+
}
14+
15+
export function set<T extends { [key: string]: any }>(target: T, field: PropertyPath, value: any) {
16+
lodashSet(target, field, cloneDeep(value));
17+
return target;
18+
}

0 commit comments

Comments
 (0)