Skip to content

Commit 7b67970

Browse files
authored
Merge pull request formio#389 from formio/fix-formBuilder-recreates-instance-on-each-rerender
FIO-2660: Fixes an issue where FormBuilder reacreats a formiojs instance on each update
2 parents 06b197b + 2dc68cf commit 7b67970

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

src/components/FormBuilder.jsx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {useEffect} from 'react';
1+
import React, {useEffect, useRef, useState, useCallback, useLayoutEffect} from 'react';
22
import PropTypes from 'prop-types';
33
import AllComponents from 'formiojs/components';
44
import Components from 'formiojs/components/Components';
@@ -7,8 +7,7 @@ import FormioFormBuilder from 'formiojs/FormBuilder';
77
Components.setComponents(AllComponents);
88

99
const FormBuilder = (props) => {
10-
let builder;
11-
let builderReady;
10+
const builderRef = useRef();
1211
let element;
1312

1413
const emit = (funcName) => (...args) => {
@@ -21,7 +20,7 @@ const FormBuilder = (props) => {
2120
const onChange = () => {
2221
const {onChange} = props;
2322
if (onChange && typeof onChange === 'function') {
24-
onChange(builder.instance.form);
23+
onChange(builderRef.current.instance.form);
2524
}
2625
};
2726

@@ -41,27 +40,45 @@ const FormBuilder = (props) => {
4140

4241
const initializeBuilder = (builderProps) => {
4342
let {options, form} = builderProps;
43+
if (!form || !form.components) return;
4444
const {Builder} = builderProps;
4545
options = Object.assign({}, options);
4646
form = Object.assign({}, form);
4747

48-
builder = new Builder(element.firstChild, form, options);
49-
builderReady = builder.ready;
48+
builderRef.current = new Builder(element, form, options);
5049

51-
builderReady.then(() => {
50+
builderRef.current.ready.then(() => {
5251
onChange();
53-
builderEvents.forEach(({name, action}) => builder.instance.on(name, action));
52+
builderEvents.forEach(({name, action}) => builderRef.current.instance.on(name, action));
5453
});
5554
};
5655

5756
useEffect(() => {
5857
initializeBuilder(props);
59-
return () => builder ? builder.instance.destroy(true) : null;
60-
}, [props.form.display, props.form.components, props.options]);
58+
return () => (builderRef.current ? builderRef.current.instance.destroy(true) : null)
59+
}, [builderRef]);
60+
61+
62+
const elementDidMount = useCallback((el) => element = el);
63+
64+
useLayoutEffect(() => {
65+
if (builderRef.current && props.form && props.form.display) {
66+
builderRef.current.setDisplay(props.form.display);
67+
}
68+
}, [props.form.display]);
69+
70+
useLayoutEffect(() => {
71+
if (builderRef.current && props.form && props.form.components) {
72+
builderRef.current.setForm(props.form);
73+
}
74+
if (!builderRef.current && props.form) {
75+
initializeBuilder(props);
76+
}
77+
}, [props.form]);
6178

6279
return (
63-
<div ref={el => element = el}>
64-
<div></div>
80+
<div>
81+
<div ref={elementDidMount}></div>
6582
</div>
6683
);
6784
};

src/components/FormEdit.jsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ const reducer = (form, {type, value}) => {
2424
formCopy.path = _camelCase(value).toLowerCase();
2525
}
2626
break;
27-
default:
28-
return form;
2927
}
3028
_set(formCopy, type, value);
3129
return formCopy;

0 commit comments

Comments
 (0)