Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compatible zustand 4.4 createWithEqualFn #56

Merged
merged 3 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions __mocks__/zustand.ts → __mocks__/zustand/traditional.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { act } from 'react-dom/test-utils';
import { beforeEach } from 'vitest';
import { create as actualCreate } from 'zustand';
import { createWithEqualityFn as actualCreate } from 'zustand/traditional';

// a variable to hold reset functions for all stores declared in the app
const storeResetFns = new Set();
const storeResetFns = new Set<() => void>();

// when creating a store, we get its initial state, create a reset function and add it in the set
const createImpl = (createState) => {
const store = actualCreate(createState);
const store = actualCreate(createState, Object.is);
const initialState = store.getState();
storeResetFns.add(() => store.setState(initialState, true));
return store;
Expand All @@ -22,8 +22,6 @@ beforeEach(() => {
);
});

export const create = (f) => (f === undefined ? createImpl : createImpl(f));
export const createWithEqualityFn = (f) => (f === undefined ? createImpl : createImpl(f));

export default create;

export { useStore } from 'zustand';
export { useStoreWithEqualityFn as useStore } from 'zustand/traditional';
6 changes: 4 additions & 2 deletions docs/pro-editor/demos/realtimeCollaboration/store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { yjsMiddleware } from '@ant-design/pro-editor';
import isEqual from 'fast-deep-equal';
import { Doc } from 'yjs';
import type { StoreApi } from 'zustand';
import { create } from 'zustand';
import { createContext } from 'zustand-utils';
import { createWithEqualityFn } from 'zustand/traditional';

interface Store {
count: number;
Expand All @@ -14,7 +15,7 @@ interface Store {
export const doc = new Doc();

export const createStore = () =>
create<Store>(
createWithEqualityFn<Store>(
yjsMiddleware<Store>(doc, 'shared', (set) => ({
count: 0,
text: '',
Expand All @@ -26,6 +27,7 @@ export const createStore = () =>
})),
updateText: (text) => set((state) => ({ ...state, text })),
})),
isEqual,
);

export const { useStore, Provider } = createContext<StoreApi<Store>>();
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@
"umi-request": "^1.4.0",
"use-merge-value": "^1.2.0",
"yjs": "^13.6.7",
"zustand": "^4.4.0",
"zustand": "^4.4.1",
"zustand-middleware-yjs": "^1.3.1",
"zustand-utils": "^1.3.0"
"zustand-utils": "^1.3.1"
},
"devDependencies": {
"@emotion/jest": "^11.11.0",
Expand Down
7 changes: 4 additions & 3 deletions src/Awareness/store.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// FIXME:这里理论上不应该使用 faker 的,后续需要重构优化掉
import { faker } from '@faker-js/faker';
import isEqual from 'fast-deep-equal';
import { useEffect } from 'react';
import type { Position } from 'react-rnd';
import type { Awareness } from 'y-protocols/awareness';
import type { WebrtcProvider } from 'y-webrtc';
import type { StoreApi } from 'zustand';
import { create } from 'zustand';
import { createContext } from 'zustand-utils';
import { createWithEqualityFn } from 'zustand/traditional';

import { useAwarenessEvent } from './event';

Expand All @@ -33,7 +34,7 @@ interface ProviderStore {
}

export const createStore = (provider: WebrtcProvider) => {
const useStore = create<ProviderStore>((set) => {
const useStore = createWithEqualityFn<ProviderStore>((set) => {
return {
provider,
awareness: provider.awareness,
Expand All @@ -44,7 +45,7 @@ export const createStore = (provider: WebrtcProvider) => {
set({ followUser });
},
};
});
}, isEqual);
const { awareness } = useStore.getState();

// eslint-disable-next-line react-hooks/rules-of-hooks
Expand Down
6 changes: 4 additions & 2 deletions src/ComponentAsset/store/createAssetStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import isEqual from 'fast-deep-equal';
import { ReactNode } from 'react';
import { StateCreator, StoreApi, create } from 'zustand';
import { StateCreator, StoreApi } from 'zustand';
import { UseContextStore, createContext, optionalDevtools } from 'zustand-utils';
import { DevtoolsOptions } from 'zustand/middleware';
import { createWithEqualityFn } from 'zustand/traditional';

import type { ProEditorInstance } from '@/ProEditor';

Expand Down Expand Up @@ -34,7 +36,7 @@ export const createAssetStore = <T>(

const devtools = optionalDevtools(!(options?.devtools === false));

return create<T>()(devtools(createStore, devtoolsOptions));
return createWithEqualityFn<T>()(devtools(createStore, devtoolsOptions), isEqual);
};

return { Provider, createStore: store, useStoreApi };
Expand Down
28 changes: 16 additions & 12 deletions src/ComponentAsset/store/createTestAssetStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { create } from 'zustand';
import isEqual from 'fast-deep-equal';
import { createWithEqualityFn } from 'zustand/traditional';

import { CreateAssetStore } from './createAssetStore';

Expand All @@ -7,21 +8,24 @@ import { CreateAssetStore } from './createAssetStore';
* @param createStore
*/
export const createTestAssetStore = <T>(createStore: CreateAssetStore<T>) => {
const useEditorStore = create<{
const useEditorStore = createWithEqualityFn<{
config: T;
setConfig: (config: T) => void;
getConfig: () => T;
}>((set, get) => ({
config: null,
setConfig: (config) => {
set({ config: { ...get().config, ...config } });
},
getConfig: () => {
return get().config;
},
}));
}>(
(set, get) => ({
config: null,
setConfig: (config) => {
set({ config: { ...get().config, ...config } });
},
getConfig: () => {
return get().config;
},
}),
isEqual,
);

const useAssetStore = create<T>(createStore);
const useAssetStore = createWithEqualityFn<T>(createStore, isEqual);
const { getConfig, setConfig } = useEditorStore.getState();

const init = () => {
Expand Down
10 changes: 5 additions & 5 deletions src/DataFill/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import isEqual from 'fast-deep-equal';
import { fromEvent, Subject } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import type { StoreApi } from 'zustand';
import { create } from 'zustand';
import { createContext } from 'zustand-utils';
import { createWithEqualityFn } from 'zustand/traditional';

import DataFiller from '../DataFiller';
import type { ShowDemoDataPayload } from '../types';
Expand All @@ -21,7 +22,7 @@ export interface DataFillAction {
export type DataFillStore = DataFillState & DataFillAction;

const createStore = () =>
create<DataFillStore>((set, get) => {
createWithEqualityFn<DataFillStore>((set, get) => {
// 处理鼠标交互处理

const mouseMoveIn$ = new Subject<ShowDemoDataPayload>();
Expand Down Expand Up @@ -65,9 +66,8 @@ const createStore = () =>
},
handleShowDemoData: (payload) => mouseMoveIn$.next(payload),
};
});
}, isEqual);

const { Provider, useStore, useStoreApi } =
createContext<StoreApi<DataFillStore>>();
const { Provider, useStore, useStoreApi } = createContext<StoreApi<DataFillStore>>();

export { createStore, Provider, useStore, useStoreApi };
8 changes: 6 additions & 2 deletions src/IconPicker/store/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import isEqual from 'fast-deep-equal';
import type { StoreApi } from 'zustand';
import { create } from 'zustand';
import { createContext, optionalDevtools } from 'zustand-utils';
import { createWithEqualityFn } from 'zustand/traditional';

import type { Store } from './store';
import vanillaStore from './store';

export const createStore = (showDevtools?: boolean) =>
create<Store>()(optionalDevtools(showDevtools)(vanillaStore, { name: 'IconPicker' }));
createWithEqualityFn<Store>()(
optionalDevtools(showDevtools)(vanillaStore, { name: 'IconPicker' }),
isEqual,
);

export const { Provider, useStore, useStoreApi } = createContext<StoreApi<Store>>();
12 changes: 3 additions & 9 deletions src/IconPicker/store/store.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import isEqual from 'fast-deep-equal';
import produce from 'immer';
import isEqual from 'lodash.isequal';
import type { StateCreator } from 'zustand/vanilla';
import type { ExternalScripts, IconUnit } from '../types';
import {
extractListFormIconfontJS,
findNeighborIndex,
} from '../utils/iconfont';
import { extractListFormIconfontJS, findNeighborIndex } from '../utils/iconfont';

import type { State } from './initialState';
import { initialState } from './initialState';
Expand All @@ -23,10 +20,7 @@ export interface Action {

export type Store = State & Action;

const vanillaStore: StateCreator<Store, [['zustand/devtools', never]]> = (
set,
get,
) => ({
const vanillaStore: StateCreator<Store, [['zustand/devtools', never]]> = (set, get) => ({
...initialState,

resetIcon: () => {
Expand Down
2 changes: 1 addition & 1 deletion src/ProEditor/store/createStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
import type { CanvasInteractRule, InteractStatus } from '../../InteractContainer';
import { createStore } from './createStore';

vi.mock('zustand');
vi.mock('zustand/traditional');

const useStore = createStore();

Expand Down
8 changes: 6 additions & 2 deletions src/ProEditor/store/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import isEqual from 'fast-deep-equal';
import type { StateCreator } from 'zustand';
import { create } from 'zustand';
import { optionalDevtools } from 'zustand-utils';
import { DevtoolsOptions } from 'zustand/middleware';
import { createWithEqualityFn } from 'zustand/traditional';

import { AwarenessSlice, AwarenessSliceState, awarenessSlice } from './slices/awareness';
import { CanvasSlice, PublicCanvasState, canvasSlice } from './slices/canvas';
Expand Down Expand Up @@ -42,5 +43,8 @@ export const createStore = (options: boolean | DevtoolsOptions = false) => {
const devtoolOptions =
options === false ? undefined : options === true ? { name: 'ProEditorStore' } : options;

return create<InternalProEditorStore>()(devtools(vanillaStore, devtoolOptions));
return createWithEqualityFn<InternalProEditorStore>()(
devtools(vanillaStore, devtoolOptions),
isEqual,
);
};
8 changes: 6 additions & 2 deletions src/SortableList/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import isEqual from 'fast-deep-equal';
import type { StoreApi } from 'zustand';
import { create } from 'zustand';
import { createContext, optionalDevtools } from 'zustand-utils';
import { createWithEqualityFn } from 'zustand/traditional';

import type { Store } from './store';
import vanillaStore from './store';

const createStore = (showDevTools: boolean) =>
create(optionalDevtools(showDevTools)(vanillaStore, { name: 'SortableList' }));
createWithEqualityFn(
optionalDevtools(showDevTools)(vanillaStore, { name: 'SortableList' }),
isEqual,
);

const { useStore, useStoreApi, Provider } = createContext<StoreApi<Store>>();

Expand Down
8 changes: 6 additions & 2 deletions src/SortableTree/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import isEqual from 'fast-deep-equal';
import type { StoreApi } from 'zustand';
import { create } from 'zustand';
import { createContext, optionalDevtools } from 'zustand-utils';
import { createWithEqualityFn } from 'zustand/traditional';

import type { InternalSortableTreeStore } from './store';
import vanillaStore from './store';

const createStore = (showDevTools: boolean) =>
create(optionalDevtools(showDevTools)(vanillaStore, { name: 'SortableTree' }));
createWithEqualityFn(
optionalDevtools(showDevTools)(vanillaStore, { name: 'SortableTree' }),
isEqual,
);

const { useStore, useStoreApi, Provider } = createContext<StoreApi<InternalSortableTreeStore>>();

Expand Down