Skip to content

Commit

Permalink
🐛 fix(pro-editor): 修正与 assetStore 的数据同步问题
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Jun 15, 2023
1 parent 713b5c8 commit 67735e2
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 22 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"highlight.js": "~10.5.0",
"immer": "^9.0.7",
"leva": "^0.9.35",
"lodash-es": "^4",
"lodash.flatten": "^4.4.0",
"lodash.get": "^4.4.2",
"lodash.isempty": "^4.4.0",
Expand All @@ -112,7 +113,7 @@
"use-merge-value": "^1",
"yjs": "^13",
"zustand": "^4",
"zustand-middleware-yjs": "^1.2.8",
"zustand-middleware-yjs": "^1.3.1",
"zustand-utils": "^1"
},
"devDependencies": {
Expand Down
56 changes: 39 additions & 17 deletions src/ProEditor/components/AssetStoreUpdater/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import isEqual from 'fast-deep-equal';
import { memo, useEffect } from 'react';
import { storeApiSetState } from 'zustand-utils';
import { shallow } from 'zustand/shallow';

import { useProEditor } from '../../hooks/useProEditor';
Expand All @@ -19,39 +20,60 @@ const AssetStoreUpdater = memo(() => {
);
const assetStoreApi = useAssetStoreApi();

const setState = (state, action: any) => (assetStoreApi.setState as any)(state, false, action);

useEffect(() => {
setState(instance, { type: '⏬ 注入 editor 方法', payload: Object.keys(instance) });
storeApiSetState(assetStoreApi, instance, false, {
type: '⏬ 注入 editor 方法',
payload: Object.keys(instance),
});
}, []);

// 将计算后的默认值传给面板
// 用等式做一次优化,不然每次都会重新计算
const defaultConfig = useStore(
(s) =>
s.componentAsset.defaultConfig || configSelector(s.componentAsset.getDefaultConfig(s.mode)),
isEqual,
);
const defaultConfig = useStore((s) => {
let config;
if (s.componentAsset.defaultConfig) {
config = s.componentAsset.defaultConfig;
} else {
if (s.componentAsset.configSelector) {
config = s.componentAsset.configSelector(s.componentAsset.getDefaultConfig(s.mode));
} else {
config = s.componentAsset.getDefaultConfig(s.mode);
}
}

const proEditorStoreApi = useStoreApi();
return config;
}, isEqual);

const syncState = (state) => setState(state, { type: '🔄 从 Editor 同步状态', payload: state });
const proEditorStoreApi = useStoreApi();

// 用 defaultConfig 更新一次config
// 用 defaultConfig 更新 config
useEffect(() => {
if (!!config) return;
const state = { config: defaultConfig };
proEditorStoreApi.setState(state);
storeApiSetState(proEditorStoreApi, state, false, {
type: '⏬ 注入初始化 config',
payload: state,
});
proEditorStoreApi.getState().yjsDoc.updateHistoryData(state);

setConfig(config, syncState);
}, []);
setConfig(defaultConfig, (state) => {
storeApiSetState(assetStoreApi, state, false, { type: '🔄 初始化状态', payload: state });
});
}, [defaultConfig]);

// 将 proEditorStore 的 config 自动同步到 assetStore
useEffect(() => {
const assetConfig = configSelector(assetStoreApi.getState());
if (isEqual(assetConfig, config)) return;
if (!!config) {
const assetConfig = configSelector(assetStoreApi.getState());
if (isEqual(assetConfig, config)) return;

setConfig(config, syncState);
setConfig(config, (state) => {
storeApiSetState(assetStoreApi, state, false, {
type: '🔄 同步 Editor 状态',
payload: state,
});
});
}
}, [config]);

return null;
Expand Down
11 changes: 7 additions & 4 deletions src/ProEditor/container/StoreUpdater.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import isEqual from 'fast-deep-equal';
import { memo, MutableRefObject, useImperativeHandle } from 'react';
import { createStoreUpdater } from 'zustand-utils';
import { createStoreUpdater, storeApiSetState } from 'zustand-utils';

import { ProEditorInstance, useProEditor } from '../hooks/useProEditor';
import type { ProEditorState } from '../store';
Expand Down Expand Up @@ -29,24 +29,27 @@ const StoreUpdater = memo(
const storeApi = useStoreApi();
const useStoreUpdater = createStoreUpdater(storeApi);
const { yjsDoc } = storeApi.getState();

// 结合 yjs 进行变更
const useUpdateWithYjs = (key: 'config', value: any) => {
useStoreUpdater(key, value, [value], (partialNewState) => {
// 如果相等,不需要更新
if (isEqual(value, storeApi.getState()[key])) return;

storeApi.setState(partialNewState);
storeApiSetState(storeApi, partialNewState, false, {
type: `📶 useUpdateWithYjs / ${key}`,
payload: value,
});

yjsDoc.updateHistoryData(partialNewState);
});
};

useStoreUpdater('mode', mode);
useUpdateWithYjs('config', config);
useStoreUpdater('assetAwareness', assetAwareness);
useStoreUpdater('editorAwareness', editorAwareness);

useUpdateWithYjs('config', config);

// 为了在受控模式下避免不必要的渲染,将下面的对象只做第一次加载
useStoreUpdater('componentAsset', componentAsset, []);
useStoreUpdater('onAssetAwarenessChange', onAssetAwarenessChange, []);
Expand Down

0 comments on commit 67735e2

Please sign in to comment.