├── .npmrc ├── .gitignore ├── jest.setup.js ├── .npmignore ├── .eslintrc.json ├── __tests__ └── index.js ├── lib └── index.js ├── package.json └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | @evilfactory:registry=https://npm.pkg.github.com/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.swp 3 | *.swp 4 | dist/ 5 | *.log 6 | -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom/extend-expect' 2 | import '@testing-library/react/cleanup-after-each'; 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | coverage 2 | fixtures 3 | __test__ 4 | .* 5 | *.log 6 | docs/ 7 | examples/ 8 | rollup.config.js 9 | jest.config.js 10 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:react/recommended" 10 | ], 11 | "globals": { 12 | "Atomics": "readonly", 13 | "SharedArrayBuffer": "readonly" 14 | }, 15 | "parserOptions": { 16 | "ecmaFeatures": { 17 | "jsx": true 18 | }, 19 | "ecmaVersion": 2018, 20 | "sourceType": "module" 21 | }, 22 | "plugins": [ 23 | "react", 24 | "jest" 25 | ], 26 | "rules": {} 27 | } 28 | -------------------------------------------------------------------------------- /__tests__/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {useGlobalState, StateProvider} from '../lib' 3 | import {fireEvent, render} from '@testing-library/react' 4 | 5 | const Provider = jest.fn(StateProvider) 6 | 7 | test('StateProvider & useGlobalState test', () => { 8 | 9 | const Props ={ 10 | reducer: (state, action) => { 11 | switch(action.type){ 12 | case 'TEST': return { 13 | ...state, 14 | test: true 15 | } 16 | default: return state 17 | } 18 | }, 19 | initialState: {test: false} 20 | } 21 | 22 | const ShowTest = () => { 23 | const [{test}] = useGlobalState() 24 | return ( 25 | 26 | {JSON.stringify(test)} 27 | 28 | ) 29 | } 30 | 31 | const ChangeTest = () => { 32 | const [, dispatch] = useGlobalState() 33 | 34 | const handleClick = () => { 35 | dispatch({ 36 | type: 'TEST' 37 | }) 38 | } 39 | 40 | return () 41 | } 42 | 43 | const {container, getByTestId } = render( 44 | 45 | 46 | 47 | 48 | ) 49 | 50 | const showTest = getByTestId('showTest') 51 | const changeTest = getByTestId('changeTest') 52 | 53 | expect(Provider).toHaveBeenCalled() 54 | expect(showTest).toHaveTextContent('false') 55 | expect(container).toBeInTheDocument() 56 | 57 | fireEvent.click(changeTest) 58 | expect(showTest).toHaveTextContent('true') 59 | 60 | }) 61 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * Main Function of useGlobalState 4 | * 5 | * https://github.com/evilfactorylabs/useGlobalState 6 | * 7 | * @version 1.0.0 8 | */ 9 | import { 10 | createElement, 11 | createContext, 12 | useContext, 13 | useReducer, 14 | } from 'react' 15 | 16 | 17 | /** 18 | * @ignore 19 | * @var {createContext} StateContext 20 | */ 21 | const StateContext = createContext() 22 | 23 | /** 24 | * @name 25 | * @param {Object} props 26 | * @property {Function} reducer **{@link https://reactjs.org/docs/hooks-reference.html#usereducer | useReducer}** 27 | * @property {Object} initialState 28 | * @property {Element} children **{@link https://reactjs.org/docs/react-api.html#createelement | createElement}** 29 | * @description 30 | * **** as Wrapper of your `React` Application. 31 | * 32 | * @example Example Use of ``. 33 | * import React from 'react' 34 | * import App from './you-app.js' 35 | * import {StateProvider} from 'evilfactorylabs/global-state' 36 | * 37 | * const initialState = { todo: [] } 38 | * 39 | * function todoReducer(state, action) { 40 | * switch (action.type) { 41 | * case "ADD_TODO": 42 | * return { 43 | * ...state, 44 | * todo: [...state.todo, action.todo] 45 | * }; 46 | * default: 47 | * return state; 48 | * } 49 | * } 50 | * 51 | * ReactDOM.render( 52 | * 53 | * 54 | * 55 | * , document.getElementById('root')) 56 | * 57 | */ 58 | export const StateProvider = ({reducer, initialState, children }) => createElement(StateContext.Provider, { 59 | value: useReducer(reducer, initialState) 60 | }, children) 61 | 62 | 63 | /** 64 | * @function useGlobalState 65 | * @name useGlobalState 66 | * @param {Function=} newAction [optional] 67 | * @example 68 | * import {useGlobalState} from '@evilfactorylabs/global-state' 69 | * 70 | * ... 71 | * const createTodo = (state, action, todo) => { 72 | * return action({ 73 | * type: 'ADD_TODO', 74 | * data: todo, 75 | * }) 76 | * } 77 | * 78 | * const [,addTodo] = useGlobalState(createTodo) 79 | * 80 | * addTodo({title: 'New Task'}) 81 | * ... 82 | */ 83 | 84 | export const useGlobalState = (newAction) => { 85 | const [state, action] = useContext(StateContext) 86 | // newAction is action injector 87 | return [state, newAction ? newAction.bind(null, state, action) : action ] 88 | } 89 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@evilfactory/global-state", 3 | "version": "0.0.1", 4 | "description": "⚛️ Simple State Management from react to react powered by React Hook.", 5 | "repository": "git@github.com:evilfactorylabs/useGlobalState.git", 6 | "author": "ri7nz ", 7 | "license": "MIT", 8 | "private": false, 9 | "peerDependencies": { 10 | "react": "^16.8.0" 11 | }, 12 | "files": [ 13 | "lib", 14 | "dist" 15 | ], 16 | "jest": { 17 | "bail": true, 18 | "browser": true, 19 | "displayName": "global-state v0.0.1", 20 | "testEnvironment": "jest-environment-jsdom", 21 | "transform": { 22 | "^.+\\.[t|j]sx?$": "babel-jest" 23 | }, 24 | "setupFilesAfterEnv": [ 25 | "./jest.setup.js" 26 | ], 27 | "testMatch": [ 28 | "**/__tests__/**/*.js?(x)" 29 | ], 30 | "verbose": true 31 | }, 32 | "babel": { 33 | "presets": [ 34 | [ 35 | "@babel/preset-env", 36 | { 37 | "targets": { 38 | "node": true 39 | } 40 | } 41 | ], 42 | "@babel/preset-react" 43 | ], 44 | "plugins": [] 45 | }, 46 | "source": "lib/index.js", 47 | "main": "dist/index.js", 48 | "module": "dist/index.m.js", 49 | "unpkg": "dist/index.umd.js", 50 | "scripts": { 51 | "build": "npm-run-all --silent -p build:* -s size", 52 | "build:microbundle": "microbundle", 53 | "size": "strip-json-comments --no-whitespace dist/*.js | gzip-size ", 54 | "build:docs": "documentation readme lib/*.js -q --section API && yarn fixreadme", 55 | "dev": "microbundle --watch", 56 | "lint": "eslint ./lib --fix", 57 | "prepare": "rm -rf dist && yarn test && yarn build", 58 | "release": "yarn -s prepare && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", 59 | "test": "jest", 60 | "test:watch": "jest --watch", 61 | "fixreadme": "node -e 'var fs=require(\"fs\");fs.writeFileSync(\"README.md\", fs.readFileSync(\"README.md\", \"utf8\").replace(/^- /gm, \"- \"))'", 62 | "docs": "documentation readme lib/*.js -q --section API && yarn fixreadme" 63 | }, 64 | "devDependencies": { 65 | "@babel/core": "^7.5.5", 66 | "@babel/preset-env": "7.5.5", 67 | "@babel/preset-react": "7.0.0", 68 | "@testing-library/jest-dom": "4.0.0", 69 | "@testing-library/react": "8.0.7", 70 | "babel-jest": "24.8.0", 71 | "documentation": "12.0.3", 72 | "eslint": "6.1.0", 73 | "eslint-plugin-jest": "22.14.0", 74 | "eslint-plugin-react": "7.14.3", 75 | "gzip-size-cli": "3.0.0", 76 | "jest": "24.8.0", 77 | "microbundle": "0.11.0", 78 | "npm-run-all": "4.1.5", 79 | "react": "16.11.0", 80 | "react-dom": "16.8.6", 81 | "strip-json-comments-cli": "1.0.1" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `@evilfactory/global-state` 2 | 3 | ⚛️ Simple State Management from react to react powered by React Hook. 4 | 5 | # Install 6 | 7 | - [Yarn](https://yarnpkg.com/en/) 8 | 9 | ```bash 10 | $ yarn add -E @evilfactory/global-state 11 | ``` 12 | 13 | - [NPM](https://www.npmjs.com/) 14 | 15 | ```bash 16 | $ npm i @evilfactory/global-state 17 | ``` 18 | 19 | ## Usage 20 | 21 | - [Example CodeSandbox](https://codesandbox.io/s/evilfactoryglobal-state-example-rc4b4) 22 | 23 | 24 | 25 | # Features 26 | 27 | - [x] Zero configuration ✅. 28 | - [x] React hooks based API ✅. 29 | - [x] React Native supported ✅. 30 | - [x] Global State & shareable ✅. 31 | - [ ] Redux Dev Tools supported 🙏. 32 | 33 | # API 34 | 35 | 36 | 37 | ### Table of Contents 38 | 39 | - [StateProvider](#stateprovider) 40 | - [Parameters](#parameters) 41 | - [Properties](#properties) 42 | - [Examples](#examples) 43 | - [useGlobalState](#useglobalstate) 44 | - [Parameters](#parameters-1) 45 | - [Examples](#examples-1) 46 | 47 | ## StateProvider 48 | 49 | **** as Wrapper of your `React` Application. 50 | 51 | ### Parameters 52 | 53 | - `props` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** 54 | - `props.reducer` 55 | - `props.initialState` 56 | - `props.children` 57 | 58 | ### Properties 59 | 60 | - `reducer` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** **[| useReducer](https://reactjs.org/docs/hooks-reference.html#usereducer)** 61 | - `initialState` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** 62 | - `children` **[Element](https://developer.mozilla.org/docs/Web/API/Element)** **[| createElement](https://reactjs.org/docs/react-api.html#createelement)** 63 | 64 | ### Examples 65 | 66 | Example Use of ``. 67 | 68 | 69 | ```javascript 70 | import React from 'react' 71 | import App from './you-app.js' 72 | import {StateProvider} from 'evilfactorylabs/global-state' 73 | 74 | const initialState = { todo: [] } 75 | 76 | function todoReducer(state, action) { 77 | switch (action.type) { 78 | case "ADD_TODO": 79 | return { 80 | ...state, 81 | todo: [...state.todo, action.todo] 82 | }; 83 | default: 84 | return state; 85 | } 86 | } 87 | 88 | ReactDOM.render( 89 | 90 | 91 | 92 | , document.getElementById('root')) 93 | ``` 94 | 95 | ## useGlobalState 96 | 97 | ### Parameters 98 | 99 | - `newAction` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** [optional] 100 | 101 | ### Examples 102 | 103 | ```javascript 104 | import {useGlobalState} from '@evilfactorylabs/global-state' 105 | 106 | ... 107 | const createTodo = (state, action, todo) => { 108 | return action({ 109 | type: 'ADD_TODO', 110 | data: todo, 111 | }) 112 | } 113 | 114 | const [,addTodo] = useGlobalState(createTodo) 115 | 116 | addTodo({title: 'New Task'}) 117 | ... 118 | ``` 119 | --------------------------------------------------------------------------------