Skip to content
Open
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
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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",
Expand Down
39 changes: 29 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@ import { useState, useEffect } from 'react'
import shouldUpdate from './utils/shouldUpdate'
import isFn from './utils/isFn'

type Reducer<TStore> = <TAction>(store: TStore, action: TAction) => TStore
type Reducer<TStore, TAction> = (store: TStore, action: TAction) => TStore
type ReducerAction<R extends Reducer<any, any>> = R extends Reducer<any, infer A> ? A : never;

type Listener<TStore> = {
mapState: (store: TStore) => TStore
updater: React.Dispatch<React.SetStateAction<TStore>>
type Listener = {
mapState: (store: any) => any
updater: React.Dispatch<React.SetStateAction<any>>
}

const createStore = <TStore>(
const createStore = <TStore, R extends Reducer<TStore, any>>(
initialStore: TStore,
reducer?: Reducer<TStore>
reducer?: R
) => {
let store: TStore = initialStore
const listeners = new Set<Listener<TStore>>()
const listeners = new Set<Listener>()

const getStore = () => store

const dispatch = (action: TStore | ((prev: TStore) => TStore)) => {
const dispatch = (action: TStore | ((prev: TStore) => TStore) | ReducerAction<R>) => {
const oldStore = store

if (reducer) {
Expand All @@ -35,7 +36,25 @@ const createStore = <TStore>(
})
}

const useStore = (mapState = (s: TStore) => s) => {
const pickStore = <K extends keyof TStore>(mapState:((s: TStore) => Pick<TStore, K>) = (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<TStore>()

useEffect(() => {
Expand All @@ -53,7 +72,7 @@ const createStore = <TStore>(
return mapState(store)
}

return [useStore, dispatch, getStore] as const
return [useStore, dispatch, getStore, pickStore] as const
}

export default createStore