Skip to content

Commit

Permalink
fix: fix incorrect unmount (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
bocembocem authored Mar 21, 2023
1 parent cc498ff commit 592652b
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 6 deletions.
12 changes: 11 additions & 1 deletion src/lib/core/components/Form/Controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,29 @@ export interface ControllerProps<Value extends FieldValue, SpecType extends Spec
childErrors: Record<string, ValidateError>,
) => void)
| null;
parentOnUnmount: ((childName: string) => void) | null;
}

export const Controller = <Value extends FieldValue, SpecType extends Spec>({
spec,
name,
initialValue,
parentOnChange,
parentOnUnmount,
}: ControllerProps<Value, SpecType>) => {
const {tools} = useDynamicFormsCtx();
const {inputEntity, Layout} = useComponents(spec);
const render = useRender({name, spec, inputEntity, Layout});
const validate = useValidate(spec);
const renderProps = useField({name, initialValue, spec, validate, tools, parentOnChange});
const renderProps = useField({
name,
initialValue,
spec,
validate,
tools,
parentOnChange,
parentOnUnmount,
});

if (_.isString(name) && isCorrectSpec(spec)) {
return render(renderProps);
Expand Down
1 change: 1 addition & 0 deletions src/lib/core/components/Form/DynamicField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const DynamicField: React.FC<DynamicFieldProps> = ({name, spec, config, M
spec={spec}
name={name}
parentOnChange={null}
parentOnUnmount={null}
initialValue={_.get(tools.initialValue, name)}
/>
{watcher}
Expand Down
4 changes: 3 additions & 1 deletion src/lib/core/components/Form/hooks/useField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface FieldProps<Value extends FieldValue, SpecType extends Spec> {
childErrors: Record<string, ValidateError>,
) => void)
| null;
parentOnUnmount: ((childName: string) => void) | null;
}

export const useField = <Value extends FieldValue, SpecType extends Spec>({
Expand All @@ -36,6 +37,7 @@ export const useField = <Value extends FieldValue, SpecType extends Spec>({
validate: propsValidate,
tools,
parentOnChange,
parentOnUnmount,
}: FieldProps<Value, SpecType>): FieldRenderProps<Value> => {
const firstRenderRef = React.useRef(true);

Expand Down Expand Up @@ -249,7 +251,7 @@ export const useField = <Value extends FieldValue, SpecType extends Spec>({
firstRenderRef.current = false;

return () => {
(parentOnChange ? parentOnChange : tools.onChange)(name, state.value, {[name]: false});
(parentOnUnmount ? parentOnUnmount : tools.onUnmount)(name);
};
}, []);

Expand Down
8 changes: 8 additions & 0 deletions src/lib/core/components/Form/hooks/useStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ export const useStore = (name: string) => {
values: _.set({...store.values}, name, value),
errors: errors || {},
})),
onUnmount: (name: string) =>
setStore((store) => ({
...store,
errors: _.omit(
store.errors,
Object.keys(store.errors).filter((key) => key.startsWith(name)),
),
})),
submitFailed,
}),
[store.initialValue, setStore, submitFailed],
Expand Down
1 change: 1 addition & 0 deletions src/lib/core/components/Form/types/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface DynamicFormsContext {
tools: {
initialValue: FieldObjectValue;
onChange: (name: string, value: FieldValue, errors?: Record<string, ValidateError>) => void;
onUnmount: (name: string) => void;
submitFailed: boolean;
};
}
10 changes: 8 additions & 2 deletions src/lib/kit/components/Inputs/ArrayBase/ArrayBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {

if (!spec.items?.required) {
if (isArraySpec(spec.items)) {
item = {OBJECT_ARRAY_FLAG: true, OBJECT_ARRAY_CNT: 0};
item = {[OBJECT_ARRAY_FLAG]: true, [OBJECT_ARRAY_CNT]: 0};
} else if (isObjectSpec(spec.items)) {
item = {};
}
Expand Down Expand Up @@ -86,6 +86,11 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {
[input.onChange, input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) => input.onChange((currentValue) => currentValue, {[childName]: false}),
[input.onChange],
);

const items = React.useMemo(
() =>
keys.map((key, idx) => {
Expand All @@ -99,13 +104,14 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {
<Controller
initialValue={input.value?.[`<${key}>`]}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
spec={itemSpec}
name={`${name}.<${key}>`}
key={`${name}.<${key}>`}
/>
);
}),
[keys.join(''), name, getItemSpec, parentOnChange, input.value],
[keys.join(''), name, getItemSpec, parentOnChange, parentOnUnmount, input.value],
);

if (!itemSpecCorrect) {
Expand Down
6 changes: 6 additions & 0 deletions src/lib/kit/components/Inputs/CardOneOf/CardOneOf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export const CardOneOf: ObjectIndependentInput = (props) => {
[input.onChange, input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) => input.onChange((currentValue) => currentValue, {[childName]: false}),
[input.onChange],
);

useErrorChecker({name, meta, open, setOpen});

return (
Expand All @@ -74,6 +79,7 @@ export const CardOneOf: ObjectIndependentInput = (props) => {
spec={specProperties[oneOfValue]}
name={`${name}.${oneOfValue}`}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
key={`${name}.${oneOfValue}`}
/>
) : null}
Expand Down
16 changes: 15 additions & 1 deletion src/lib/kit/components/Inputs/ObjectBase/ObjectBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export const ObjectBase: ObjectIndependentInput = ({spec, name, Layout, ...restP
[restProps.input.onChange, restProps.input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) =>
restProps.input.onChange((currentValue) => currentValue, {[childName]: false}),
[restProps.input.onChange],
);
const content = React.useMemo(() => {
if (!_.isObjectLike(spec.properties) || !Object.keys(spec.properties || {}).length) {
return null;
Expand All @@ -67,13 +72,22 @@ export const ObjectBase: ObjectIndependentInput = ({spec, name, Layout, ...restP
spec={specProperties[property]}
name={`${name ? name + '.' : ''}${property}`}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
key={`${name ? name + '.' : ''}${property}`}
/>
) : null,
)}
</React.Fragment>
);
}, [spec.properties, spec.viewSpec.order, name, restProps.input.value, addBtn, parentOnChange]);
}, [
spec.properties,
spec.viewSpec.order,
name,
restProps.input.value,
addBtn,
parentOnChange,
parentOnUnmount,
]);

if (!Layout || !content) {
return content;
Expand Down
7 changes: 7 additions & 0 deletions src/lib/kit/components/Inputs/OneOf/OneOf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ export const OneOf: ObjectIndependentInput = (props) => {
[props.input.onChange, props.input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) =>
props.input.onChange((currentValue) => currentValue, {[childName]: false}),
[props.input.onChange],
);

return (
<div className={b()}>
{specProperties[oneOfValue] ? (
Expand All @@ -36,6 +42,7 @@ export const OneOf: ObjectIndependentInput = (props) => {
spec={specProperties[oneOfValue]}
name={`${props.name}.${oneOfValue}`}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
key={`${props.name}.${oneOfValue}`}
/>
</GroupIndent>
Expand Down
6 changes: 6 additions & 0 deletions src/lib/kit/components/Inputs/OneOfCard/OneOfCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ export const OneOfCard: ObjectIndependentInput = (props) => {
[input.onChange, input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) => input.onChange((currentValue) => currentValue, {[childName]: false}),
[input.onChange],
);

useErrorChecker({name, meta, open, setOpen});

return (
Expand All @@ -92,6 +97,7 @@ export const OneOfCard: ObjectIndependentInput = (props) => {
spec={specProperties[oneOfValue]}
name={`${name}.${oneOfValue}`}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
key={`${name}.${oneOfValue}`}
/>
) : null}
Expand Down
6 changes: 6 additions & 0 deletions src/lib/kit/components/Inputs/Secret/Secret.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export const Secret: ObjectIndependentInput = ({spec, name, input}) => {
[input.onChange, input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) => input.onChange((currentValue) => currentValue, {[childName]: false}),
[input.onChange],
);

if (!_.isObjectLike(spec.properties)) {
return null;
}
Expand All @@ -43,6 +48,7 @@ export const Secret: ObjectIndependentInput = ({spec, name, input}) => {
spec={specProperties[SECRET_PROPERTY_NAME]}
name={`${name}.${SECRET_PROPERTY_NAME}`}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
key={`${name}.${SECRET_PROPERTY_NAME}`}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ export const TableArrayInput: ArrayInput = ({spec, name, arrayInput, input}) =>
[input.onChange, input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) => input.onChange((currentValue) => currentValue, {[childName]: false}),
[input.onChange],
);

const columns = React.useMemo(() => {
const {
items,
Expand Down Expand Up @@ -129,14 +134,15 @@ export const TableArrayInput: ArrayInput = ({spec, name, arrayInput, input}) =>
spec={entitySpec}
name={`${name}.<${key}>.${property}`}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
/>
</div>
);
},
}));

return [idxColumn, ...columns, removeColumn];
}, [name, spec, onItemRemove, parentOnChange, input.value]);
}, [name, spec, onItemRemove, parentOnChange, parentOnUnmount, input.value]);

if (!columns) {
return null;
Expand Down
7 changes: 7 additions & 0 deletions src/stories/components/InputPreview/SpecSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ export const SpecSelector: ObjectIndependentInput = (props) => {
[props.input.onChange, props.input.name],
);

const parentOnUnmount = React.useCallback(
(childName: string) =>
props.input.onChange((currentValue) => currentValue, {[childName]: false}),
[props.input.onChange],
);

const typeSpec = React.useMemo(
() => ({
type: SpecTypes.String,
Expand All @@ -87,6 +93,7 @@ export const SpecSelector: ObjectIndependentInput = (props) => {
spec={optionsSpec}
name={`${props.name}.${type}`}
parentOnChange={parentOnChange}
parentOnUnmount={parentOnUnmount}
key={`${props.name}.${type}`}
/>
</React.Fragment>
Expand Down

0 comments on commit 592652b

Please sign in to comment.