Skip to content

Commit 90f1b46

Browse files
authored
Merge pull request #770 from rvsia/moveResolvePropsToTop
fix(renderer): move resolve props to top
2 parents 5211639 + 98500f2 commit 90f1b46

File tree

3 files changed

+68
-15
lines changed

3 files changed

+68
-15
lines changed

packages/react-form-renderer/demo/form-template.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ const FormTemplate = ({ schema: { title, description }, formFields }) => {
1212
{description && <h2>{description}</h2>}
1313
{formFields}
1414
<FormSpy>
15-
{({ submitting, pristine, validating, form: { reset }, values }) => (
15+
{({ submitting, pristine, validating, valid, form: { reset }, values }) => (
1616
<React.Fragment>
17+
{JSON.stringify({ pristine, valid })}
1718
<button key="form-submit" type="submit" disabled={submitting || validating || isDisabled(['invalid'], getState)}>
1819
Submit
1920
</button>

packages/react-form-renderer/demo/index.js

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,54 @@
11
/* eslint-disable camelcase */
22
import React from 'react';
33
import ReactDOM from 'react-dom';
4-
import FormRenderer, { useFieldApi, validatorTypes, componentTypes } from '../src';
4+
import FormRenderer, { useFieldApi, componentTypes, validatorTypes } from '../src';
55
import componentMapper from './form-fields-mapper';
66
import FormTemplate from './form-template';
77

88
// eslint-disable-next-line react/prop-types
9-
const TextField = ({ name, label }) => {
10-
const { input } = useFieldApi({ name, validate: [{ type: validatorTypes.REQUIRED }] });
9+
const TextField = (props) => {
10+
const { input, label, isRequired } = useFieldApi(props);
1111
return (
1212
<div>
13-
<label>{label}</label>
13+
<label>
14+
{label}
15+
{isRequired && '*'}
16+
</label>
1417
<input {...input} />
1518
</div>
1619
);
1720
};
1821

22+
let key;
23+
1924
const fileSchema = {
2025
fields: [
2126
{
2227
component: 'text-field',
23-
name: 'foo',
24-
label: 'Foo'
28+
name: 'required',
29+
label: 'required'
30+
},
31+
{
32+
component: 'text-field',
33+
name: 'field',
34+
label: 'field',
35+
resolveProps: (y, x, formOptions) => {
36+
const value = formOptions.getFieldState('required')?.value;
37+
38+
//console.log({ value });
39+
40+
if (value) {
41+
key = key || Date.now();
42+
43+
return {
44+
isRequired: true,
45+
validate: [{ type: validatorTypes.REQUIRED }],
46+
key
47+
};
48+
} else {
49+
key = undefined;
50+
}
51+
}
2552
}
2653
]
2754
};
@@ -38,6 +65,7 @@ const App = () => {
3865
onSubmit={(values, ...args) => console.log(values, args)}
3966
FormTemplate={FormTemplate}
4067
schema={fileSchema}
68+
subscription={{ values: true }}
4169
/>
4270
</div>
4371
);

packages/react-form-renderer/src/files/use-field-api.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,27 @@ const reducer = (state, { type, specialType, validate, arrayValidator, initialVa
5757
}
5858
};
5959

60+
const createFieldProps = (name, formOptions) => {
61+
const { value, blur, change, focus, ...meta } = formOptions.getFieldState(name) || {};
62+
63+
return {
64+
meta,
65+
input: { name, value }
66+
};
67+
};
68+
6069
const useFieldApi = ({ name, initializeOnMount, component, render, validate, resolveProps, ...props }) => {
6170
const { validatorMapper, formOptions } = useContext(RendererContext);
6271

72+
const { validate: resolvePropsValidate, ...resolvedProps } = resolveProps
73+
? resolveProps(props, createFieldProps(name, formOptions), formOptions) || {}
74+
: {};
75+
76+
const finalValidate = resolvePropsValidate || validate;
77+
6378
const [{ type, initialValue, validate: stateValidate, arrayValidator }, dispatch] = useReducer(
6479
reducer,
65-
{ props, validate, component, validatorMapper },
80+
{ props: { ...props, ...resolvedProps }, validate: finalValidate, component, validatorMapper },
6681
init
6782
);
6883

@@ -71,6 +86,7 @@ const useFieldApi = ({ name, initializeOnMount, component, render, validate, res
7186
const enhancedProps = {
7287
type,
7388
...props,
89+
...resolvedProps,
7490
...(initialValue ? { initialValue } : {}),
7591
...(stateValidate ? { validate: stateValidate } : {})
7692
};
@@ -92,8 +108,8 @@ const useFieldApi = ({ name, initializeOnMount, component, render, validate, res
92108
if (mounted.current) {
93109
dispatch({
94110
type: 'setValidators',
95-
validate: calculateValidate(props, validate, component, validatorMapper),
96-
arrayValidator: calculateArrayValidator(props, validate, component, validatorMapper)
111+
validate: calculateValidate(enhancedProps, finalValidate, component, validatorMapper),
112+
arrayValidator: calculateArrayValidator(enhancedProps, finalValidate, component, validatorMapper)
97113
});
98114
}
99115
/**
@@ -102,20 +118,20 @@ const useFieldApi = ({ name, initializeOnMount, component, render, validate, res
102118
* Using stringify is acceptable here since the array is usually very small.
103119
* If we notice performance hit, we can implement custom hook with a deep equal functionality.
104120
*/
105-
}, [validate ? JSON.stringify(validate) : false, component, props.dataType]);
121+
}, [finalValidate ? JSON.stringify(finalValidate) : false, component, enhancedProps.dataType]);
106122

107123
/** Re-convert initialValue when changed */
108124
useEffect(() => {
109125
if (mounted.current) {
110-
const newInitialValue = calculateInitialValue(props);
126+
const newInitialValue = calculateInitialValue(enhancedProps);
111127
if (!isEqual(initialValue, newInitialValue)) {
112128
dispatch({
113129
type: 'setInitialValue',
114130
initialValue: newInitialValue
115131
});
116132
}
117133
}
118-
}, [props.initialValue, props.dataType]);
134+
}, [enhancedProps.initialValue, enhancedProps.dataType]);
119135

120136
useEffect(() => {
121137
/**
@@ -160,14 +176,22 @@ const useFieldApi = ({ name, initializeOnMount, component, render, validate, res
160176
[]
161177
);
162178

163-
const { initialValue: _initialValue, clearOnUnmount, dataType, clearedValue, isEqual: _isEqual, ...cleanProps } = props;
179+
const {
180+
initialValue: _initialValue,
181+
clearOnUnmount,
182+
dataType,
183+
clearedValue,
184+
isEqual: _isEqual,
185+
validate: _validate,
186+
type: _type,
187+
...cleanProps
188+
} = enhancedProps;
164189

165190
/**
166191
* construct component props necessary that would live in field provider
167192
*/
168193
return {
169194
...cleanProps,
170-
...(resolveProps ? resolveProps(cleanProps, fieldProps, formOptions) : {}),
171195
...fieldProps,
172196
...(arrayValidator ? { arrayValidator } : {}),
173197
input: {

0 commit comments

Comments
 (0)