2
0
Эх сурвалжийг харах

fix(material): json-schema-editor onChange in setState callback (#887)

Yiwei Mao 3 сар өмнө
parent
commit
0ce2903024

+ 60 - 53
packages/materials/form-materials/src/components/json-schema-editor/hooks.tsx

@@ -27,6 +27,7 @@ export function usePropertiesEdit(
   const canAddField = typeManager.canAddField(value || {});
 
   const [propertyList, setPropertyList] = useState<PropertyValueType[]>([]);
+  const latestPropertyListRef = useRef(propertyList);
 
   const effectVersion = useRef(0);
   const changeVersion = useRef(0);
@@ -39,77 +40,82 @@ export function usePropertiesEdit(
     effectVersion.current = changeVersion.current;
 
     // If the value is changed, update the property list
-    setPropertyList((_list) => {
-      const newNames = Object.entries(drilldownSchema?.properties || {})
-        .sort(([, a], [, b]) => (a.extra?.index ?? 0) - (b.extra?.index ?? 0))
-        .map(([key]) => key);
-
-      const oldNames = _list.map((item) => item.name).filter(Boolean) as string[];
-      const addNames = difference(newNames, oldNames);
-
-      return _list
-        .filter((item) => !item.name || newNames.includes(item.name))
-        .map((item) => ({
-          key: item.key,
-          name: item.name,
-          isPropertyRequired: drilldownSchema?.required?.includes(item.name || '') || false,
-          ...(drilldownSchema?.properties?.[item.name || ''] || item || {}),
+    const _list = latestPropertyListRef.current;
+
+    const newNames = Object.entries(drilldownSchema?.properties || {})
+      .sort(([, a], [, b]) => (a.extra?.index ?? 0) - (b.extra?.index ?? 0))
+      .map(([key]) => key);
+
+    const oldNames = _list.map((item) => item.name).filter(Boolean) as string[];
+    const addNames = difference(newNames, oldNames);
+
+    const next = _list
+      .filter((item) => !item.name || newNames.includes(item.name))
+      .map((item) => ({
+        key: item.key,
+        name: item.name,
+        isPropertyRequired: drilldownSchema?.required?.includes(item.name || '') || false,
+        ...(drilldownSchema?.properties?.[item.name || ''] || item || {}),
+      }))
+      .concat(
+        addNames.map((_name) => ({
+          key: genId(),
+          name: _name,
+          isPropertyRequired: drilldownSchema?.required?.includes(_name) || false,
+          ...(drilldownSchema?.properties?.[_name] || {}),
         }))
-        .concat(
-          addNames.map((_name) => ({
-            key: genId(),
-            name: _name,
-            isPropertyRequired: drilldownSchema?.required?.includes(_name) || false,
-            ...(drilldownSchema?.properties?.[_name] || {}),
-          }))
-        );
-    });
+      );
+
+    latestPropertyListRef.current = next;
+
+    setPropertyList(next);
   }, [drilldownSchema]);
 
   const updatePropertyList = (updater: (list: PropertyValueType[]) => PropertyValueType[]) => {
     changeVersion.current = changeVersion.current + 1;
 
-    setPropertyList((_list) => {
-      const next = updater(_list);
+    const next = updater(latestPropertyListRef.current);
+    latestPropertyListRef.current = next;
+    setPropertyList(next);
 
-      // onChange to parent
-      const nextProperties: Record<string, IJsonSchema> = {};
-      const nextRequired: string[] = [];
+    // onChange to parent
+    const nextProperties: Record<string, IJsonSchema> = {};
+    const nextRequired: string[] = [];
 
-      for (const _property of next) {
-        if (!_property.name) {
-          continue;
-        }
+    for (const _property of next) {
+      if (!_property.name) {
+        continue;
+      }
 
-        nextProperties[_property.name] = omit(_property, ['key', 'name', 'isPropertyRequired']);
+      nextProperties[_property.name] = omit(_property, ['key', 'name', 'isPropertyRequired']);
 
-        if (_property.isPropertyRequired) {
-          nextRequired.push(_property.name);
-        }
+      if (_property.isPropertyRequired) {
+        nextRequired.push(_property.name);
       }
+    }
 
-      onChange?.(
-        produce(value || {}, (draft) => {
-          const propertiesParent = typeManager.getPropertiesParent(draft);
-
-          if (propertiesParent) {
-            propertiesParent.properties = nextProperties;
-            propertiesParent.required = nextRequired;
-            return;
-          }
-        })
-      );
+    onChange?.(
+      produce(value || {}, (draft) => {
+        const propertiesParent = typeManager.getPropertiesParent(draft);
 
-      return next;
-    });
+        if (propertiesParent) {
+          propertiesParent.properties = nextProperties;
+          propertiesParent.required = nextRequired;
+          return;
+        }
+      })
+    );
   };
 
   const onAddProperty = () => {
-    // set property list only, not trigger updatePropertyList
-    setPropertyList((_list) => [
+    const _list = latestPropertyListRef.current;
+    const next = [
       ..._list,
       { key: genId(), name: '', type: 'string', extra: { index: _list.length + 1 } },
-    ]);
+    ];
+
+    latestPropertyListRef.current = next;
+    setPropertyList(next);
   };
 
   const onRemoveProperty = (key: number) => {
@@ -124,6 +130,7 @@ export function usePropertiesEdit(
 
   useEffect(() => {
     if (!canAddField) {
+      latestPropertyListRef.current = [];
       setPropertyList([]);
     }
   }, [canAddField]);