react-hooks-global-state
Advanced tools
Comparing version 0.0.3 to 0.0.4
@@ -5,2 +5,7 @@ # Change Log | ||
## [0.0.4] - 2018-11-05 | ||
### Changed | ||
- Redux-like createStore | ||
- Update README | ||
## [0.0.3] - 2018-11-04 | ||
@@ -7,0 +12,0 @@ ### Added |
@@ -1,2 +0,2 @@ | ||
import { createGlobalState } from '../../src/index'; | ||
import { createStore } from '../../src/index'; | ||
@@ -18,11 +18,3 @@ type Action = { | ||
const { dispatch, stateItemHooks } = createGlobalState( | ||
{ | ||
counter: 0, | ||
person: { | ||
age: 0, | ||
firstName: '', | ||
lastName: '', | ||
}, | ||
}, | ||
const { dispatch, stateItemHooks } = createStore( | ||
(state, action: Action) => { | ||
@@ -62,2 +54,10 @@ switch (action.type) { | ||
}, | ||
{ | ||
counter: 0, | ||
person: { | ||
age: 0, | ||
firstName: '', | ||
lastName: '', | ||
}, | ||
}, | ||
); | ||
@@ -64,0 +64,0 @@ |
{ | ||
"name": "react-hooks-global-state", | ||
"description": "Simple global state for React by Hooks API", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"author": "Daishi Kato", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -25,2 +25,4 @@ react-hooks-global-state | ||
### setState style | ||
```javascript | ||
@@ -39,3 +41,4 @@ import React from 'react'; | ||
<span>Counter: {value}</span> | ||
<button onClick={() => update(v => v + 1)}>Click</button> | ||
<button onClick={() => update(v => v + 1)}>+1</button> | ||
<button onClick={() => update(v => v - 1)}>-1</button> | ||
</div> | ||
@@ -53,2 +56,38 @@ ); | ||
### reducer style | ||
```javascript | ||
import React from 'react'; | ||
import { createStore } from 'react-hooks-global-state'; | ||
const reducer = (state, action) => { | ||
switch (action.type) { | ||
case: 'increment': return { ...state, counter: state.counter + 1 }; | ||
case: 'decrement': return { ...state, counter: state.counter - 1 }; | ||
default: return state; | ||
} | ||
}; | ||
const initialState = { counter: 0 }; // initialState is not optional. | ||
const { dispatch, stateItemHooks } = createStore(reducer, initialState); | ||
const useCounter = stateItemHooks.counter; | ||
const Counter = () => { | ||
const [value] = useCounter(); | ||
return ( | ||
<div> | ||
<span>Counter: {value}</span> | ||
<button onClick={() => dispatch({ type: 'increment' })}>+1</button> | ||
<button onClick={() => dispatch({ type: 'decrement' })}>-1</button> | ||
</div> | ||
); | ||
}; | ||
const App = () => ( | ||
<div> | ||
<Counter /> | ||
<Counter /> | ||
</div> | ||
); | ||
``` | ||
Example | ||
@@ -70,1 +109,2 @@ ------- | ||
- [TypeScript-aware React hooks for global state](https://medium.com/@dai_shi/typescript-aware-react-hooks-for-global-state-b6e2dfc0e9a7) | ||
- [An alternative to React Redux by React Hooks API (For both JavaScript and TypeScript)](https://medium.com/@dai_shi/an-alternative-to-react-redux-by-react-hooks-api-for-both-javascript-and-typescript-c5e9a351ba0b) |
@@ -7,6 +7,18 @@ export type StateItemUpdater<T> = (f: ((v: T) => T) | T) => void; | ||
export type CreateGlobalState = | ||
<S extends {}, A extends {}>(initialState: S, reducer?: Reducer<S, A>) => { | ||
stateItemUpdaters: { [K in keyof S]: StateItemUpdater<S[K]> }, | ||
export type Store<S, A> = { | ||
getState: () => S, | ||
dispatch: (action: A) => void, | ||
}; | ||
export type Enhancer<S, A> = (store: Store<S, A>) => Store<S, A>; | ||
export type CreateGlobalState = <S extends {}, A extends {}>(initialState: S) => { | ||
stateItemHooks: { [K in keyof S]: StateItemHook<S[K]> }, | ||
stateItemUpdaters: { [K in keyof S]: StateItemUpdater<S[K]> }, | ||
}; | ||
export type CreateStore = <S extends {}, A extends {}>( | ||
reducer: Reducer<S, A>, initialState: S, enhancer?: Enhancer<S, A>) => { | ||
stateItemHooks: { [K in keyof S]: StateItemHook<S[K]> }, | ||
getState: () => S, | ||
dispatch: (action: A) => void; | ||
@@ -16,1 +28,2 @@ }; | ||
export const createGlobalState: CreateGlobalState; | ||
export const createStore: CreateStore; |
import { useState, useEffect } from 'react'; | ||
// utility functions | ||
const map = (obj, func) => { | ||
const newObj = {}; | ||
Object.keys(obj).forEach((key) => { | ||
newObj[key] = func(obj[key]); | ||
}); | ||
Object.keys(obj).forEach((key) => { newObj[key] = func(obj[key]); }); | ||
return newObj; | ||
}; | ||
const isFunction = fn => (typeof fn === 'function'); | ||
const defaultReducer = state => state; | ||
const defaultEnhancer = store => store; | ||
// core functions | ||
const createStateItem = (initialValue) => { | ||
@@ -40,12 +42,28 @@ let value = initialValue; | ||
const createDispatch = (stateItemMap, reducer) => { | ||
const createGetState = (stateItemMap, initialState) => { | ||
const keys = Object.keys(stateItemMap); | ||
let globalState = initialState; | ||
const getState = () => { | ||
let changed = false; | ||
const currentState = {}; | ||
// XXX an extra overhead here | ||
keys.forEach((key) => { | ||
currentState[key] = stateItemMap[key].getValue(); | ||
if (currentState[key] !== globalState[key]) changed = true; | ||
}); | ||
if (changed) globalState = currentState; | ||
return globalState; | ||
}; | ||
return getState; | ||
}; | ||
const createDispatch = (stateItemMap, getState, reducer) => { | ||
const keys = Object.keys(stateItemMap); | ||
const dispatch = (action) => { | ||
const oldState = {}; | ||
Object.keys(stateItemMap).forEach((name) => { | ||
oldState[name] = stateItemMap[name].getValue(); | ||
}); | ||
const oldState = getState(); | ||
const newState = reducer(oldState, action); | ||
Object.keys(oldState).forEach((name) => { | ||
if (oldState[name] !== newState[name]) { | ||
stateItemMap[name].updater(newState[name]); | ||
if (oldState === newState) return; | ||
keys.forEach((key) => { | ||
if (oldState[key] !== newState[key]) { | ||
stateItemMap[key].updater(newState[key]); | ||
} | ||
@@ -57,3 +75,5 @@ }); | ||
export const createGlobalState = (initialState, reducer = defaultReducer) => { | ||
// export functions | ||
export const createGlobalState = (initialState) => { | ||
const stateItemMap = map(initialState, createStateItem); | ||
@@ -63,4 +83,13 @@ return { | ||
stateItemHooks: Object.freeze(map(stateItemMap, x => x.hook)), | ||
dispatch: createDispatch(stateItemMap, reducer), | ||
}; | ||
}; | ||
export const createStore = (reducer, initialState, enhancer = defaultEnhancer) => { | ||
const stateItemMap = map(initialState, createStateItem); | ||
const getState = createGetState(stateItemMap, initialState); | ||
const dispatch = createDispatch(stateItemMap, getState, reducer); | ||
return { | ||
stateItemHooks: Object.freeze(map(stateItemMap, x => x.hook)), | ||
...enhancer({ getState, dispatch }), | ||
}; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32097
817
107