Skip to content

Commit

Permalink
Merge pull request #56 from ant-design/fix/zustand-4.4
Browse files Browse the repository at this point in the history
compatible zustand 4.4 createWithEqualFn
  • Loading branch information
arvinxx authored Aug 22, 2023
2 parents 762cd3b + 0595717 commit a789e54
Show file tree
Hide file tree
Showing 13 changed files with 68 additions and 51 deletions.
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

0 comments on commit a789e54

Please sign in to comment.