Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-hooks-global-state

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-hooks-global-state - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

examples/09_comparison/App.tsx

21

__tests__/01_basic_spec.js

@@ -21,6 +21,5 @@ /* eslint-env jest */

};
const { stateItemHooks } = createGlobalState(initialState);
const useCounter1 = stateItemHooks.counter1;
const { GlobalStateProvider, useGlobalState } = createGlobalState(initialState);
const Counter = () => {
const [value, update] = useCounter1();
const [value, update] = useGlobalState('counter1');
return (

@@ -34,10 +33,12 @@ <div>

const App = () => (
<div>
<div className="first">
<Counter />
<GlobalStateProvider>
<div>
<div className="first">
<Counter />
</div>
<div className="second">
<Counter />
</div>
</div>
<div className="second">
<Counter />
</div>
</div>
</GlobalStateProvider>
);

@@ -44,0 +45,0 @@ const wrapper = mount(<App />);

@@ -5,2 +5,6 @@ # Change Log

## [0.3.0] - 2018-11-12
### Changed
- New API using Context and observedBits
## [0.2.0] - 2018-11-09

@@ -7,0 +11,0 @@ ### Changed

@@ -40,2 +40,3 @@ "use strict";

var createEnhancers = function createEnhancers() {
var savedReducer;
var savedInitialState;

@@ -45,2 +46,3 @@

return function (reducer, initialState, enhancer) {
savedReducer = reducer;
savedInitialState = initialState;

@@ -67,3 +69,3 @@ if (enhancer) return enhancer(createStore)(reducer, initialState);

if (enhancer) return enhancer(createStore)(reducer, initialState);
var store = createStore(null, savedInitialState);
var store = createStore(savedReducer, savedInitialState);

@@ -77,14 +79,6 @@ var devState = _objectSpread({}, reducer(initialState, initAction()), savedInitialState);

var listeners = [];
var keys = Object.keys(savedInitialState);
var dispatch = function dispatch(action) {
devState = reducer(devState, action);
keys.forEach(function (key) {
var value = devState.computedStates[devState.currentStateIndex].state[key];
var stateItem = store.stateItemMap[key];
if (stateItem.getValue() !== value) {
stateItem.updater(value);
}
});
store.setState(devState.computedStates[devState.currentStateIndex].state);
listeners.forEach(function (f) {

@@ -91,0 +85,0 @@ return f();

@@ -23,47 +23,43 @@ "use strict";

// utility functions
var map = function map(obj, func) {
var newObj = {};
Object.keys(obj).forEach(function (key) {
newObj[key] = func(obj[key]);
});
return newObj;
};
var isFunction = function isFunction(fn) {
return typeof fn === 'function';
}; // core functions
};
var updateValue = function updateValue(oldValue, newValue) {
if (isFunction(newValue)) {
return newValue(oldValue);
}
var createStateItem = function createStateItem(initialValue) {
var value = initialValue;
return newValue;
}; // core functions
var getValue = function getValue() {
return value;
};
var createGlobalStateCommon = function createGlobalStateCommon(initialState) {
var keys = Object.keys(initialState);
var globalState = initialState;
var listeners = [];
var updater = function updater(funcOrVal) {
if (isFunction(funcOrVal)) {
value = funcOrVal(value);
} else {
value = funcOrVal;
}
listeners.forEach(function (f) {
return f(value);
var calculateChangedBits = function calculateChangedBits(a, b) {
var bits = 0;
keys.forEach(function (k, i) {
if (a[k] !== b[k]) bits |= 1 << i;
});
return bits;
};
var hook = function hook() {
var _useState = (0, _react.useState)(value),
var context = (0, _react.createContext)(initialState, calculateChangedBits);
var GlobalStateProvider = function GlobalStateProvider(_ref) {
var children = _ref.children;
var _useState = (0, _react.useState)(initialState),
_useState2 = _slicedToArray(_useState, 2),
val = _useState2[0],
setVal = _useState2[1];
state = _useState2[0],
setState = _useState2[1];
(0, _react.useEffect)(function () {
listeners.push(setVal);
listeners.push(setState);
var cleanup = function cleanup() {
var index = listeners.indexOf(setVal);
var index = listeners.indexOf(setState);
listeners.splice(index, 1);

@@ -74,50 +70,41 @@ };

}, []);
return [val, updater];
return (0, _react.createElement)(context.Provider, {
value: state
}, children);
};
return {
getValue: getValue,
updater: updater,
hook: hook
var setGlobalState = function setGlobalState(name, update) {
globalState = _objectSpread({}, globalState, _defineProperty({}, name, updateValue(globalState[name], update)));
listeners.forEach(function (f) {
return f(globalState);
});
};
};
var createGetState = function createGetState(stateItemMap, initialState) {
var keys = Object.keys(stateItemMap);
var globalState = initialState;
var useGlobalState = function useGlobalState(name) {
var index = keys.indexOf(name);
var state = (0, _react.useContext)(context, 1 << index);
var updater = (0, _react.useCallback)(function (u) {
return setGlobalState(name, u);
}, [name]);
return [state[name], updater];
};
var getState = function getState() {
var changed = false;
var currentState = {}; // XXX an extra overhead here
return globalState;
};
keys.forEach(function (key) {
currentState[key] = stateItemMap[key].getValue();
if (currentState[key] !== globalState[key]) changed = true;
var setState = function setState(state) {
globalState = state;
listeners.forEach(function (f) {
return f(globalState);
});
if (changed) globalState = currentState;
return globalState;
};
return getState;
};
var createDispatch = function createDispatch(stateItemMap, getState, reducer) {
var keys = Object.keys(stateItemMap);
var dispatch = function dispatch(action) {
var oldState = getState();
var newState = reducer(oldState, action);
if (oldState !== newState) {
keys.forEach(function (key) {
if (oldState[key] !== newState[key]) {
stateItemMap[key].updater(newState[key]);
}
});
}
return action;
return {
GlobalStateProvider: GlobalStateProvider,
setGlobalState: setGlobalState,
useGlobalState: useGlobalState,
getState: getState,
setState: setState
};
return dispatch;
}; // export functions

@@ -127,10 +114,11 @@

var createGlobalState = function createGlobalState(initialState) {
var stateItemMap = map(initialState, createStateItem);
var _createGlobalStateCom = createGlobalStateCommon(initialState),
GlobalStateProvider = _createGlobalStateCom.GlobalStateProvider,
useGlobalState = _createGlobalStateCom.useGlobalState,
setGlobalState = _createGlobalStateCom.setGlobalState;
return {
useGlobalState: function useGlobalState(name) {
return stateItemMap[name].hook();
},
setGlobalState: function setGlobalState(name, update) {
return stateItemMap[name].updater(update);
}
GlobalStateProvider: GlobalStateProvider,
useGlobalState: useGlobalState,
setGlobalState: setGlobalState
};

@@ -143,16 +131,26 @@ };

if (enhancer) return enhancer(createStore)(reducer, initialState);
var stateItemMap = map(initialState, createStateItem);
var getState = createGetState(stateItemMap, initialState);
var dispatch = createDispatch(stateItemMap, getState, reducer);
return _objectSpread({
useGlobalState: function useGlobalState(name) {
return stateItemMap[name].hook();
},
var _createGlobalStateCom2 = createGlobalStateCommon(initialState),
GlobalStateProvider = _createGlobalStateCom2.GlobalStateProvider,
useGlobalState = _createGlobalStateCom2.useGlobalState,
getState = _createGlobalStateCom2.getState,
setState = _createGlobalStateCom2.setState;
var dispatch = function dispatch(action) {
var oldState = getState();
var newState = reducer(oldState, action);
setState(newState);
return action;
};
return {
GlobalStateProvider: GlobalStateProvider,
useGlobalState: useGlobalState,
getState: getState,
setState: setState,
// for devtools.js
dispatch: dispatch
}, reducer === null ? {
stateItemMap: stateItemMap
} : {});
};
};
exports.createStore = createStore;

@@ -12,3 +12,3 @@ /* eslint-env browser */

};
const { useGlobalState } = createGlobalState(initialState);
const { GlobalStateProvider, useGlobalState } = createGlobalState(initialState);

@@ -43,3 +43,3 @@ const Counter = () => {

const App = () => (
<div>
<GlobalStateProvider>
<h1>Counter</h1>

@@ -51,5 +51,5 @@ <Counter />

<TextBox />
</div>
</GlobalStateProvider>
);
ReactDOM.render(<App />, document.getElementById('app'));
import { createGlobalState } from '../../src/index';
export const { useGlobalState } = createGlobalState({
export const { GlobalStateProvider, useGlobalState } = createGlobalState({
counter: 0,

@@ -5,0 +5,0 @@ person: {

import { createGlobalState } from '../../src/index';
const { setGlobalState, useGlobalState } = createGlobalState({
const { GlobalStateProvider, setGlobalState, useGlobalState } = createGlobalState({
counter: 0,

@@ -32,2 +32,2 @@ person: {

export { useGlobalState };
export { GlobalStateProvider, useGlobalState };
import { createGlobalState } from '../../src/index';
const { setGlobalState, useGlobalState } = createGlobalState({
const { GlobalStateProvider, setGlobalState, useGlobalState } = createGlobalState({
errorMessage: '',

@@ -16,2 +16,2 @@ pageTitle: '',

export { useGlobalState };
export { GlobalStateProvider, useGlobalState };
import { createGlobalState } from '../../src/index';
const { setGlobalState, useGlobalState } = createGlobalState({
const { GlobalStateProvider, setGlobalState, useGlobalState } = createGlobalState({
errorMessage: '',

@@ -16,2 +16,2 @@ pageTitle: '',

export { useGlobalState };
export { GlobalStateProvider, useGlobalState };
import { createStore } from '../../src/index';
type Action = {
type: 'increment',
} | {
type: 'decrement',
} | {
type: 'setFirstName',
firstName: string,
} | {
type: 'setLastName',
lastName: string,
} | {
type: 'setAge',
age: number,
};
type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'setFirstName', firstName: string }
| { type: 'setLastName', lastName: string }
| { type: 'setAge', age: number };
export const { dispatch, useGlobalState } = createStore(
export const { GlobalStateProvider, dispatch, useGlobalState } = createStore(
(state, action: Action) => {

@@ -20,0 +12,0 @@ switch (action.type) {

@@ -16,16 +16,8 @@ import { applyMiddleware, combineReducers } from 'redux';

type Action = {
type: 'increment',
} | {
type: 'decrement',
} | {
type: 'setFirstName',
firstName: string,
} | {
type: 'setLastName',
lastName: string,
} | {
type: 'setAge',
age: number,
};
type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'setFirstName', firstName: string }
| { type: 'setLastName', lastName: string }
| { type: 'setAge', age: number };

@@ -73,3 +65,3 @@ const counterReducer = (state = initialState.counter, action: Action) => {

export const { dispatch, useGlobalState } = createStore(
export const { GlobalStateProvider, dispatch, useGlobalState } = createStore(
reducer,

@@ -76,0 +68,0 @@ initialState,

@@ -19,16 +19,8 @@ import { applyMiddleware, combineReducers, compose } from 'redux';

export type Action = {
type: 'increment',
} | {
type: 'decrement',
} | {
type: 'setFirstName',
firstName: string,
} | {
type: 'setLastName',
lastName: string,
} | {
type: 'setAge',
age: number,
};
export type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'setFirstName', firstName: string }
| { type: 'setLastName', lastName: string }
| { type: 'setAge', age: number };

@@ -66,3 +58,3 @@ const counterReducer = (state = initialState.counter, action: Action) => {

export const { dispatch, useGlobalState } = createStore<State, Action>(
export const { GlobalStateProvider, dispatch, useGlobalState } = createStore<State, Action>(
reducer,

@@ -69,0 +61,0 @@ initialState,

{
"name": "react-hooks-global-state",
"description": "Simple global state for React by Hooks API",
"version": "0.2.0",
"version": "0.3.0",
"author": "Daishi Kato",

@@ -20,10 +20,12 @@ "repository": {

"tsc-test": "tsc --project . --noEmit",
"examples:minimal": "webpack-dev-server --entry ./examples/01_minimal/main.js --content-base examples/01_minimal",
"examples:typescript": "webpack-dev-server --entry ./examples/02_typescript/main.ts --content-base examples/02_typescript",
"examples:actions": "webpack-dev-server --entry ./examples/03_actions/main.ts --content-base examples/03_actions",
"examples:fetch": "webpack-dev-server --entry ./examples/04_fetch/main.ts --content-base examples/04_fetch",
"examples:onmount": "webpack-dev-server --entry ./examples/05_onmount/main.ts --content-base examples/05_onmount",
"examples:reducer": "webpack-dev-server --entry ./examples/06_reducer/main.ts --content-base examples/06_reducer",
"examples:middleware": "webpack-dev-server --entry ./examples/07_middleware/main.ts --content-base examples/07_middleware",
"examples:thunk": "webpack-dev-server --entry ./examples/08_thunk/main.ts --content-base examples/08_thunk"
"examples:minimal": "DIR=01_minimal EXT=js webpack-dev-server",
"examples:typescript": "DIR=02_typescript webpack-dev-server",
"examples:actions": "DIR=03_actions webpack-dev-server",
"examples:fetch": "DIR=04_fetch webpack-dev-server",
"examples:onmount": "DIR=05_onmount webpack-dev-server",
"examples:reducer": "DIR=06_reducer webpack-dev-server",
"examples:middleware": "DIR=07_middleware webpack-dev-server",
"examples:thunk": "DIR=08_thunk webpack-dev-server",
"examples:comparison": "DIR=09_comparison webpack-dev-server",
"examples:immer": "DIR=10_immer webpack-dev-server"
},

@@ -41,7 +43,7 @@ "keywords": [

"devDependencies": {
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@babel/preset-env": "^7.1.0",
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.5",
"@babel/preset-env": "^7.1.5",
"@babel/preset-react": "^7.0.0",
"@types/react": "^16.4.18",
"@types/react": "^16.7.1",
"@types/react-dom": "^16.0.9",

@@ -53,5 +55,5 @@ "@types/redux-logger": "^3.0.6",

"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.6.0",
"enzyme-adapter-react-16": "^1.7.0",
"enzyme-to-json": "^3.3.4",
"eslint": "^5.7.0",
"eslint": "^5.8.0",
"eslint-config-airbnb": "^17.1.0",

@@ -61,6 +63,7 @@ "eslint-plugin-import": "^2.14.0",

"eslint-plugin-react": "^7.11.1",
"immer": "^1.7.4",
"jest": "^23.6.0",
"react": "^16.7.0-alpha.0",
"react-dom": "^16.7.0-alpha.0",
"react-use": "^3.1.0",
"react-use": "3.1.0",
"redux": "^4.0.1",

@@ -73,5 +76,5 @@ "redux-logger": "^3.0.6",

"typescript": "^3.1.6",
"webpack": "^4.24.0",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.9"
"webpack-dev-server": "^3.1.10"
},

@@ -104,3 +107,4 @@ "peerDependencies": {

"react/prop-types": 0,
"no-underscore-dangle": 0
"no-underscore-dangle": 0,
"no-bitwise": 0
}

@@ -107,0 +111,0 @@ },

@@ -32,3 +32,3 @@ react-hooks-global-state

const initialState = { counter: 0 };
const { useGlobalState } = createGlobalState(initialState);
const { GlobalStateProvider, useGlobalState } = createGlobalState(initialState);

@@ -47,6 +47,6 @@ const Counter = () => {

const App = () => (
<div>
<GlobalStateProvider>
<Counter />
<Counter />
</div>
</GlobalStateProvider>
);

@@ -69,3 +69,3 @@ ```

const initialState = { counter: 0 }; // initialState is not optional.
const { dispatch, useGlobalState } = createStore(reducer, initialState);
const { GlobalStateProvider, dispatch, useGlobalState } = createStore(reducer, initialState);

@@ -84,6 +84,6 @@ const Counter = () => {

const App = () => (
<div>
<GlobalStateProvider>
<Counter />
<Counter />
</div>
</GlobalStateProvider>
);

@@ -110,1 +110,2 @@ ```

- [Redux middleware compatible React Hooks library for easy global state management](https://medium.com/@dai_shi/redux-middleware-compatible-react-hooks-library-for-easy-global-state-management-4fe73623e69e)
- [React Hooks Tutorial on pure useReducer + useContext for global state like Redux and comparison with react-hooks-global-state](https://medium.com/@dai_shi/react-hooks-tutorial-for-pure-usereducer-usecontext-for-global-state-like-redux-and-comparison-dd3da5053624)

@@ -8,4 +8,6 @@ /* eslint-env browser */

const createEnhancers = () => {
let savedReducer;
let savedInitialState;
const before = createStore => (reducer, initialState, enhancer) => {
savedReducer = reducer;
savedInitialState = initialState;

@@ -25,3 +27,3 @@ if (enhancer) return enhancer(createStore)(reducer, initialState);

if (enhancer) return enhancer(createStore)(reducer, initialState);
const store = createStore(null, savedInitialState);
const store = createStore(savedReducer, savedInitialState);
let devState = {

@@ -33,12 +35,5 @@ ...reducer(initialState, initAction()),

const listeners = [];
const keys = Object.keys(savedInitialState);
const dispatch = (action) => {
devState = reducer(devState, action);
keys.forEach((key) => {
const value = devState.computedStates[devState.currentStateIndex].state[key];
const stateItem = store.stateItemMap[key];
if (stateItem.getValue() !== value) {
stateItem.updater(value);
}
});
store.setState(devState.computedStates[devState.currentStateIndex].state);
listeners.forEach(f => f());

@@ -45,0 +40,0 @@ return action;

@@ -0,1 +1,7 @@

import * as React from 'react';
export type GlobalStateProviderProps = {
children?: React.ReactNode,
};
export type Update<T> = ((v: T) => T) | T;

@@ -17,2 +23,3 @@

export type Store<S, A> = {
GlobalStateProvider: React.ComponentType<GlobalStateProviderProps>,
useGlobalState: UseGlobalState<S>,

@@ -28,2 +35,3 @@ getState: () => S,

export type CreateGlobalState = <S extends {}, A extends {}>(initialState: S) => {
GlobalStateProvider: React.ComponentType<GlobalStateProviderProps>,
useGlobalState: UseGlobalState<S>,

@@ -30,0 +38,0 @@ setGlobalState: SetGlobalState<S>,

@@ -1,32 +0,43 @@

import { useState, useEffect } from 'react';
import {
createContext,
createElement,
useCallback,
useContext,
useState,
useEffect,
} from 'react';
// utility functions
const map = (obj, func) => {
const newObj = {};
Object.keys(obj).forEach((key) => { newObj[key] = func(obj[key]); });
return newObj;
const isFunction = fn => (typeof fn === 'function');
const updateValue = (oldValue, newValue) => {
if (isFunction(newValue)) {
return newValue(oldValue);
}
return newValue;
};
const isFunction = fn => (typeof fn === 'function');
// core functions
const createStateItem = (initialValue) => {
let value = initialValue;
const getValue = () => value;
const createGlobalStateCommon = (initialState) => {
const keys = Object.keys(initialState);
let globalState = initialState;
const listeners = [];
const updater = (funcOrVal) => {
if (isFunction(funcOrVal)) {
value = funcOrVal(value);
} else {
value = funcOrVal;
}
listeners.forEach(f => f(value));
const calculateChangedBits = (a, b) => {
let bits = 0;
keys.forEach((k, i) => {
if (a[k] !== b[k]) bits |= 1 << i;
});
return bits;
};
const hook = () => {
const [val, setVal] = useState(value);
const context = createContext(initialState, calculateChangedBits);
const GlobalStateProvider = ({ children }) => {
const [state, setState] = useState(initialState);
useEffect(() => {
listeners.push(setVal);
listeners.push(setState);
const cleanup = () => {
const index = listeners.indexOf(setVal);
const index = listeners.indexOf(setState);
listeners.splice(index, 1);

@@ -36,39 +47,34 @@ };

}, []);
return [val, updater];
return createElement(context.Provider, { value: state }, children);
};
return { getValue, updater, hook };
};
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;
const setGlobalState = (name, update) => {
globalState = {
...globalState,
[name]: updateValue(globalState[name], update),
};
listeners.forEach(f => f(globalState));
};
return getState;
};
const createDispatch = (stateItemMap, getState, reducer) => {
const keys = Object.keys(stateItemMap);
const dispatch = (action) => {
const oldState = getState();
const newState = reducer(oldState, action);
if (oldState !== newState) {
keys.forEach((key) => {
if (oldState[key] !== newState[key]) {
stateItemMap[key].updater(newState[key]);
}
});
}
return action;
const useGlobalState = (name) => {
const index = keys.indexOf(name);
const state = useContext(context, 1 << index);
const updater = useCallback(u => setGlobalState(name, u), [name]);
return [state[name], updater];
};
return dispatch;
const getState = () => globalState;
const setState = (state) => {
globalState = state;
listeners.forEach(f => f(globalState));
};
return {
GlobalStateProvider,
setGlobalState,
useGlobalState,
getState,
setState,
};
};

@@ -79,6 +85,11 @@

export const createGlobalState = (initialState) => {
const stateItemMap = map(initialState, createStateItem);
const {
GlobalStateProvider,
useGlobalState,
setGlobalState,
} = createGlobalStateCommon(initialState);
return {
useGlobalState: name => stateItemMap[name].hook(),
setGlobalState: (name, update) => stateItemMap[name].updater(update),
GlobalStateProvider,
useGlobalState,
setGlobalState,
};

@@ -89,11 +100,21 @@ };

if (enhancer) return enhancer(createStore)(reducer, initialState);
const stateItemMap = map(initialState, createStateItem);
const getState = createGetState(stateItemMap, initialState);
const dispatch = createDispatch(stateItemMap, getState, reducer);
const {
GlobalStateProvider,
useGlobalState,
getState,
setState,
} = createGlobalStateCommon(initialState);
const dispatch = (action) => {
const oldState = getState();
const newState = reducer(oldState, action);
setState(newState);
return action;
};
return {
useGlobalState: name => stateItemMap[name].hook(),
GlobalStateProvider,
useGlobalState,
getState,
setState, // for devtools.js
dispatch,
...(reducer === null ? { stateItemMap } : {}), // for devtools.js
};
};

@@ -0,3 +1,6 @@

const { DIR, EXT = 'ts' } = process.env;
module.exports = {
mode: 'development',
entry: `./examples/${DIR}/main.${EXT}`,
output: {

@@ -28,3 +31,4 @@ filename: 'bundle.js',

port: process.env.PORT || '8080',
contentBase: `./examples/${DIR}`,
},
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc