Skip to content

Commit

Permalink
feat: 👔 supported zustand v5
Browse files Browse the repository at this point in the history
  • Loading branch information
Albert-Gao committed Dec 7, 2024
1 parent 99728ad commit 07b93d7
Show file tree
Hide file tree
Showing 10 changed files with 1,564 additions and 2,213 deletions.
35 changes: 0 additions & 35 deletions eslint.config.js

This file was deleted.

61 changes: 61 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import prettier from 'eslint-plugin-prettier';
import reactHooks from 'eslint-plugin-react-hooks';
import { fixupPluginRules } from '@eslint/compat';
import globals from 'globals';
import tsParser from '@typescript-eslint/parser';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import js from '@eslint/js';
import { FlatCompat } from '@eslint/eslintrc';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});

export default [
...compat.extends(
'prettier',
'plugin:prettier/recommended',
'plugin:@typescript-eslint/eslint-recommended'
),
{
plugins: {
'@typescript-eslint': typescriptEslint,
prettier,
'react-hooks': fixupPluginRules(reactHooks),
},

languageOptions: {
globals: {
...globals.browser,
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
},

parser: tsParser,
ecmaVersion: 2018,
sourceType: 'module',

parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},

rules: {
'prettier/prettier': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': ['error'],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'react/react-in-jsx-scope': 'off',
},
},
];
63 changes: 34 additions & 29 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"license": "MIT",
"scripts": {
"start": "rollup -c rollup.config.js -w",
"lint": "eslint ./src/index.ts --no-warn-ignored",
"lint": "eslint ./src --no-warn-ignored",
"build": "tsc && rollup -c rollup.config.mjs",
"coverage": "codecov -e TRAVIS_NODE_VERSION -f coverage/*.json",
"test": "jest --coverage",
Expand All @@ -32,44 +32,49 @@
"node": ">=18.0.0"
},
"peerDependencies": {
"zustand": "*"
"zustand": ">=5.0.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "^15.0.7",
"@types/jest": "^29.5.12",
"@types/node": "^20.12.12",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.9.0",
"@typescript-eslint/parser": "^7.9.0",
"@eslint/compat": "^1.2.4",
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.16.0",
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-terser": "0.4.4",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.1.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.14",
"@types/node": "^22.10.1",
"@types/react": "^19.0.1",
"@types/react-dom": "^19.0.1",
"@typescript-eslint/eslint-plugin": "^8.17.0",
"@typescript-eslint/parser": "^8.17.0",
"cross-env": "^7.0.3",
"eslint": "^9.3.0",
"eslint": "^9.16.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-n": "^17.7.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-n": "^17.14.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-react-hooks": "^5.1.0",
"globals": "^15.13.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"lint-staged": "^15.2.2",
"prettier": "^3.2.5",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rollup": "^4.17.2",
"lint-staged": "^15.2.10",
"prettier": "^3.4.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"rollup": "^4.28.1",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.36.0",
"ts-jest": "^29.1.2",
"typescript": "^5.4.5",
"zustand": "^4.5.2"
"ts-jest": "^29.2.5",
"typescript": "^5.7.2",
"zustand": "^5.0.2"
},
"packageManager": "[email protected].21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
"packageManager": "[email protected].22"
}
3 changes: 2 additions & 1 deletion rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import external from 'rollup-plugin-peer-deps-external';
import sourceMaps from 'rollup-plugin-sourcemaps';
import { terser } from 'rollup-plugin-terser';
import typescript from 'rollup-plugin-typescript2';
import pkg from './package.json' assert { type: 'json' };
import terser from '@rollup/plugin-terser';

/** @type {import('rollup').RollupOptions} */
const option = {
Expand Down Expand Up @@ -50,6 +50,7 @@ const option = {
commonjs(),
// Resolve source maps to the original source
sourceMaps(),
terser(),
],
};

Expand Down
8 changes: 5 additions & 3 deletions src/createSelectorFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type StoreApi, type UseBoundStore, useStore } from 'zustand';
import { useShallow } from 'zustand/react/shallow';

export interface ZustandFuncSelectors<StateType> {
use: {
Expand All @@ -15,9 +16,10 @@ export function createSelectorFunctions<StateType extends object>(

Object.keys(storeIn.getState()).forEach((key) => {
const selector = (state: StateType) => state[key as keyof StateType];
storeIn.use[key] = typeof storeIn === 'function'
? () => storeIn(selector)
: () => useStore(storeIn, selector as any);
storeIn.use[key] =
typeof storeIn === 'function'
? () => storeIn(useShallow(selector))
: () => useStore(storeIn, useShallow(selector as any));
});

return store as UseBoundStore<StoreApi<StateType>> &
Expand Down
8 changes: 5 additions & 3 deletions src/createSelectorHooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type StoreApi, type UseBoundStore, useStore } from 'zustand';
import { useShallow } from 'zustand/react/shallow';

export type ZustandHookSelectors<StateType> = {
[Key in keyof StateType as `use${Capitalize<
Expand All @@ -15,9 +16,10 @@ export function createSelectorHooks<StateType extends object>(

Object.keys(storeIn.getState()).forEach((key) => {
const selector = (state: StateType) => state[key as keyof StateType];
storeIn[`use${capitalize(key)}`] = typeof storeIn === 'function'
? () => storeIn(selector)
: () => useStore(storeIn, selector as any);
storeIn[`use${capitalize(key)}`] =
typeof storeIn === 'function'
? () => storeIn(useShallow(selector))
: () => useStore(storeIn, useShallow(selector as any));
});

return storeIn as UseBoundStore<StoreApi<StateType>> &
Expand Down
38 changes: 19 additions & 19 deletions tests/context-usage.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { createStore } from 'zustand';
import { createSelectorFunctions, createSelectorHooks } from '../src/index';
import { render, fireEvent } from '@testing-library/react';
import { render, fireEvent, screen } from '@testing-library/react';
import { combine } from 'zustand/middleware';

interface BearState {
Expand Down Expand Up @@ -108,17 +108,17 @@ describe('the Context + createSelectorFunctions() usage should work', () => {
);
};

const { getByTestId } = render(<App />);
render(<App />);

expect(getByTestId('text').textContent).toBe('0');
expect(screen.getByTestId('text').textContent).toBe('0');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('1');
expect(screen.getByTestId('text').textContent).toBe('1');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('2');
expect(screen.getByTestId('text').textContent).toBe('2');
});
});

Expand Down Expand Up @@ -161,17 +161,17 @@ describe('the Context + createSelectorHooks() usage should work', () => {
</StoreContext.Provider>
);

const { getByTestId } = render(<App />);
render(<App />);

expect(getByTestId('text').textContent).toBe('0');
expect(screen.getByTestId('text').textContent).toBe('0');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('1');
expect(screen.getByTestId('text').textContent).toBe('1');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('2');
expect(screen.getByTestId('text').textContent).toBe('2');
});

it('should work when using combine() + createSelectorHooks()', () => {
Expand Down Expand Up @@ -214,16 +214,16 @@ describe('the Context + createSelectorHooks() usage should work', () => {
</StoreContext.Provider>
);

const { getByTestId } = render(<App />);
render(<App />);

expect(getByTestId('text').textContent).toBe('0');
expect(screen.getByTestId('text').textContent).toBe('0');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('1');
expect(screen.getByTestId('text').textContent).toBe('1');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('2');
expect(screen.getByTestId('text').textContent).toBe('2');
});
});
14 changes: 7 additions & 7 deletions tests/createSelectorFunctions.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { create } from 'zustand';
import { createSelectorFunctions } from '../src/index';
import { render, fireEvent } from '@testing-library/react';
import { render, fireEvent, screen } from '@testing-library/react';

interface BearState {
bears: number;
Expand Down Expand Up @@ -51,16 +51,16 @@ describe('Test createSelectorFunctions', () => {
);
};

const { getByTestId } = render(<TestComponent />);
render(<TestComponent />);

expect(getByTestId('text').textContent).toBe('0');
expect(screen.getByTestId('text').textContent).toBe('0');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('1');
expect(screen.getByTestId('text').textContent).toBe('1');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('2');
expect(screen.getByTestId('text').textContent).toBe('2');
});
});
15 changes: 8 additions & 7 deletions tests/createSelectorHooks.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as React from 'react';
import { create } from 'zustand';
import { createSelectorHooks } from '../src/index';
import { render, fireEvent } from '@testing-library/react';
import { render, fireEvent, screen } from '@testing-library/react';
import '@testing-library/jest-dom';

interface BearState {
bears: number;
Expand Down Expand Up @@ -51,16 +52,16 @@ describe('Test createSelectorHooks', () => {
);
};

const { getByTestId } = render(<TestComponent />);
render(<TestComponent />);

expect(getByTestId('text').textContent).toBe('0');
expect(screen.getByTestId('text').textContent).toBe('0');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('1');
expect(screen.getByTestId('text').textContent).toBe('1');

fireEvent.click(getByTestId('button'));
fireEvent.click(screen.getByTestId('button'));

expect(getByTestId('text').textContent).toBe('2');
expect(screen.getByTestId('text').textContent).toBe('2');
});
});
Loading

0 comments on commit 07b93d7

Please sign in to comment.