redux-simplify-hooks 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/dist/src/hooks/useBoundAction.d.ts +1 -2
- package/dist/src/hooks/useBoundAction.d.ts.map +1 -1
- package/dist/src/hooks/useBoundAction.js +3 -3
- package/dist/src/hooks/useRedux.d.ts.map +1 -1
- package/dist/src/hooks/useRedux.js +11 -10
- package/dist/src/hooks/useReduxMulti.d.ts +1 -1
- package/dist/src/hooks/useReduxMulti.d.ts.map +1 -1
- package/dist/src/hooks/useReduxMulti.js +18 -6
- package/dist/src/hooks/useReduxState.d.ts.map +1 -1
- package/dist/src/hooks/useReduxState.js +8 -4
- package/dist/src/utils/getNestedValue.d.ts.map +1 -1
- package/dist/src/utils/getNestedValue.js +4 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function useBoundAction<Args extends any[]>(actionCreator: (...args: Args) => AnyAction): (...args: Args) => void;
|
|
1
|
+
export declare function useBoundAction<Args extends any[]>(actionCreator: (...args: Args) => any): (...args: Args) => any;
|
|
3
2
|
//# sourceMappingURL=useBoundAction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBoundAction.d.ts","sourceRoot":"","sources":["../../../src/hooks/useBoundAction.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useBoundAction.d.ts","sourceRoot":"","sources":["../../../src/hooks/useBoundAction.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,IAAI,SAAS,GAAG,EAAE,EAC/C,aAAa,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,GAAG,aAIR,IAAI,SAGlC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { useDispatch } from "react-redux";
|
|
3
3
|
export function useBoundAction(actionCreator) {
|
|
4
4
|
const dispatch = useDispatch();
|
|
5
5
|
return useCallback((...args) => {
|
|
6
|
-
dispatch(actionCreator(...args));
|
|
6
|
+
return dispatch(actionCreator(...args));
|
|
7
7
|
}, [dispatch, actionCreator]);
|
|
8
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRedux.d.ts","sourceRoot":"","sources":["../../../src/hooks/useRedux.ts"],"names":[],"mappings":"AAIA,wBAAgB,QAAQ,CAAC,CAAC,GAAG,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"useRedux.d.ts","sourceRoot":"","sources":["../../../src/hooks/useRedux.ts"],"names":[],"mappings":"AAIA,wBAAgB,QAAQ,CAAC,CAAC,GAAG,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC;WAe3C,CAAC;;EAC3B"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { useSelector, useDispatch } from 'react-redux';
|
|
2
|
-
import { useMemo } from 'react';
|
|
1
|
+
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
|
2
|
+
import { useMemo, useRef } from 'react';
|
|
3
3
|
import { getNestedValue } from '../utils/getNestedValue';
|
|
4
4
|
export function useRedux(statePath, defaultValue) {
|
|
5
5
|
const dispatch = useDispatch();
|
|
6
|
+
// Store defaultValue in a ref so changes to object literals don't break memoization
|
|
7
|
+
const defaultRef = useRef(defaultValue);
|
|
8
|
+
defaultRef.current = defaultValue;
|
|
6
9
|
const selector = useMemo(() => {
|
|
7
10
|
return (state) => {
|
|
8
|
-
if (!statePath)
|
|
9
|
-
|
|
10
|
-
return defaultValue;
|
|
11
|
-
}
|
|
11
|
+
if (!statePath)
|
|
12
|
+
return defaultRef.current;
|
|
12
13
|
const val = getNestedValue(state, statePath);
|
|
13
|
-
return val !== undefined ? val :
|
|
14
|
+
return val !== undefined ? val : defaultRef.current;
|
|
14
15
|
};
|
|
15
|
-
}, [statePath
|
|
16
|
-
const
|
|
17
|
-
return { state:
|
|
16
|
+
}, [statePath]); // Removed defaultValue from deps to keep selector stable
|
|
17
|
+
const state = useSelector(selector, shallowEqual);
|
|
18
|
+
return { state: state, dispatch };
|
|
18
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useReduxMulti.d.ts","sourceRoot":"","sources":["../../../src/hooks/useReduxMulti.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useReduxMulti.d.ts","sourceRoot":"","sources":["../../../src/hooks/useReduxMulti.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,CAAC,KAAK,GAAE,MAAM,EAAO;;;EAmBjD"}
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useSelector } from "react-redux";
|
|
2
|
+
import { useDispatch } from "react-redux";
|
|
3
|
+
import { getNestedValue } from "../utils/getNestedValue";
|
|
4
|
+
import { shallowEqual } from "react-redux";
|
|
2
5
|
export function useReduxMulti(paths = []) {
|
|
3
|
-
const dispatch =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
const dispatch = useDispatch();
|
|
7
|
+
// Memoize the path string to keep the selector identity stable
|
|
8
|
+
const pathsKey = paths.join(',');
|
|
9
|
+
const state = useSelector((rootState) => {
|
|
10
|
+
return paths.reduce((acc, path) => {
|
|
11
|
+
acc[path] = getNestedValue(rootState, path);
|
|
12
|
+
return acc;
|
|
13
|
+
}, {});
|
|
14
|
+
}, (prev, next) => {
|
|
15
|
+
// Faster than JSON.stringify, safer than default ref check
|
|
16
|
+
const keys = Object.keys(next);
|
|
17
|
+
if (keys.length !== Object.keys(prev).length)
|
|
18
|
+
return false;
|
|
19
|
+
return keys.every(key => shallowEqual(prev[key], next[key]));
|
|
7
20
|
});
|
|
8
|
-
const state = Object.fromEntries(states);
|
|
9
21
|
return { state, dispatch };
|
|
10
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useReduxState.d.ts","sourceRoot":"","sources":["../../../src/hooks/useReduxState.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useReduxState.d.ts","sourceRoot":"","sources":["../../../src/hooks/useReduxState.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,CAAC,EAC7B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,GAAG,EAChC,YAAY,CAAC,EAAE,CAAC,GACf,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAe5C"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCallback, useRef } from "react";
|
|
2
|
+
import { useRedux } from "./useRedux";
|
|
2
3
|
export function useReduxState(statePath, actionCreator, defaultValue) {
|
|
3
4
|
const { state, dispatch } = useRedux(statePath, defaultValue);
|
|
4
|
-
|
|
5
|
+
// Keep track of the latest state in a ref to avoid stale closures in useCallback
|
|
6
|
+
const stateRef = useRef(state);
|
|
7
|
+
stateRef.current = state;
|
|
8
|
+
const setState = useCallback((newValue) => {
|
|
5
9
|
const valueToDispatch = typeof newValue === 'function'
|
|
6
|
-
? newValue(
|
|
10
|
+
? newValue(stateRef.current)
|
|
7
11
|
: newValue;
|
|
8
12
|
dispatch(actionCreator(valueToDispatch));
|
|
9
|
-
};
|
|
13
|
+
}, [dispatch, actionCreator]); // state is removed from deps; setState is now stable!
|
|
10
14
|
return [state, setState];
|
|
11
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNestedValue.d.ts","sourceRoot":"","sources":["../../../src/utils/getNestedValue.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,
|
|
1
|
+
{"version":3,"file":"getNestedValue.d.ts","sourceRoot":"","sources":["../../../src/utils/getNestedValue.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAQ1D"}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
export function getNestedValue(obj, path) {
|
|
2
2
|
if (!path)
|
|
3
3
|
return obj;
|
|
4
|
-
|
|
4
|
+
const keys = path.split(/[.[\]]+/).filter(Boolean);
|
|
5
|
+
return keys.reduce((acc, key) => {
|
|
5
6
|
if (acc === undefined || acc === null)
|
|
6
7
|
return undefined;
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const [, arrKey, index] = arrayMatch;
|
|
10
|
-
return acc[arrKey]?.[Number(index)];
|
|
11
|
-
}
|
|
12
|
-
return acc?.[key];
|
|
8
|
+
const isIndex = /^\d+$/.test(key);
|
|
9
|
+
return isIndex ? acc[Number(key)] : acc[key];
|
|
13
10
|
}, obj);
|
|
14
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redux-simplify-hooks",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Redux made simple: modern, type-safe React hooks for deeply nested state, actions, and selectors — fully compatible with Redux Toolkit and React 16.8+.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|