diff --git a/package-lock.json b/package-lock.json index 9c48fd8..6abaa0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "react-superstore", - "version": "0.0.5", + "version": "0.0.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "react-superstore", - "version": "0.0.5", + "version": "0.0.6", "license": "MIT", "devDependencies": { "@types/react": "^17.0.39", "typescript": "^4.5.5" }, "peerDependencies": { - "react": ">=16.8.0" + "react": "^18.2.0" } }, "node_modules/@types/prop-types": { @@ -23,9 +23,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "17.0.39", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", - "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "version": "17.0.65", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.65.tgz", + "integrity": "sha512-oxur785xZYHvnI7TRS61dXbkIhDPnGfsXKv0cNXR/0ml4SipRIFpSMzA7HMEfOywFwJ5AOnPrXYTEiTRUQeGlQ==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -65,7 +65,7 @@ }, "node_modules/react": { "version": "18.2.0", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/react/-/react-18.2.0.tgz", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "peer": true, "dependencies": { @@ -97,9 +97,9 @@ "dev": true }, "@types/react": { - "version": "17.0.39", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", - "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "version": "17.0.65", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.65.tgz", + "integrity": "sha512-oxur785xZYHvnI7TRS61dXbkIhDPnGfsXKv0cNXR/0ml4SipRIFpSMzA7HMEfOywFwJ5AOnPrXYTEiTRUQeGlQ==", "dev": true, "requires": { "@types/prop-types": "*", @@ -136,7 +136,7 @@ }, "react": { "version": "18.2.0", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/react/-/react-18.2.0.tgz", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "peer": true, "requires": { diff --git a/package.json b/package.json index 84f6679..dfc704b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-superstore", - "version": "0.0.5", + "version": "0.0.6", "description": "Simple hook to create global state in react", "keywords": [ "react", @@ -25,7 +25,7 @@ "typescript": "^4.5.5" }, "peerDependencies": { - "react": ">=16.8.0" + "react": "^18.2.0" }, "repository": "https://github.com/stevekanger/react-superstore.git", "homepage": "https://github.com/stevekanger/react-superstore.git#readme", diff --git a/src/index.ts b/src/index.ts index 9d438a5..d8ea809 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,23 +2,24 @@ import { useState, useEffect } from 'react' import shouldUpdate from './utils/shouldUpdate' import isFn from './utils/isFn' -type Reducer = (store: TStore, action: TAction) => TStore +type Reducer = (store: TStore, action: TAction) => TStore +type ReducerAction> = R extends Reducer ? A : never; -type Listener = { - mapState: (store: TStore) => TStore - updater: React.Dispatch> +type Listener = { + mapState: (store: any) => any + updater: React.Dispatch> } -const createStore = ( +const createStore = >( initialStore: TStore, - reducer?: Reducer + reducer?: R ) => { let store: TStore = initialStore - const listeners = new Set>() + const listeners = new Set() const getStore = () => store - const dispatch = (action: TStore | ((prev: TStore) => TStore)) => { + const dispatch = (action: TStore | ((prev: TStore) => TStore) | ReducerAction) => { const oldStore = store if (reducer) { @@ -35,7 +36,25 @@ const createStore = ( }) } - const useStore = (mapState = (s: TStore) => s) => { + const pickStore = (mapState:((s: TStore) => Pick) = (s) => s) => { + const [, updater] = useState() + + useEffect(() => { + const listener = { + updater, + mapState, + } + + listeners.add(listener) + return () => { + listeners.delete(listener) + } + }, [mapState]) + + return mapState(store) + } + + const useStore = (mapState:((s: TStore) => TStore) = (s) => s) => { const [, updater] = useState() useEffect(() => { @@ -53,7 +72,7 @@ const createStore = ( return mapState(store) } - return [useStore, dispatch, getStore] as const + return [useStore, dispatch, getStore, pickStore] as const } export default createStore