Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dimapaloskin committed Nov 8, 2018
0 parents commit 7ee3ddc
Show file tree
Hide file tree
Showing 11 changed files with 1,743 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-react", "@babel/preset-flow"]
}
27 changes: 27 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"parser": "babel-eslint",
"extends": [
"standard",
"plugin:react/recommended"
],
"plugins": [
"react",
"flowtype",
"jest"
],
"rules": {
"space-before-function-paren": 0,
"comma-dangle": 0,
"flowtype/require-valid-file-annotation": 2,
"no-unused-expressions": 0,
"flowtype/no-unused-expressions": 2
},
"env": {
"jest/globals": true
},
"settings": {
"react": {
"version": "16.7"
}
}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"printWidth": 100,
"parser": "flow",
"semi": false,
"singleQuote": true,
"trailingComma": "all"
}
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# react-shared-hooks
---
POC of global react hooks. Makes it possible to use global states based on hooks.

## Usage:

```js
import * as React from 'react'
import { createSharedHook, useSharedHook, withSharedHooks } from 'react-shared-hooks'

const { useState } = React

const counter = createSharedHook(useState, { count: 0 })

const Counter = () => {
const [state, setState] = useSharedHook(hooks => hooks.counter)

return (
<div>
{state.count}
<button onClick={() => setState({ count: state.count + 1 })}>+</button>
</div>
)
}

const App = () => (
<React.Fragment>
<Counter />
<Counter />
</React.Fragment>
)

export default withSharedHooks({ counter })(App)

```

## API

### `createSharedHooks(hook, ...args)`
- `hook`: *function* - react hook
- `...args`: *any* - arguments that will be passed at the time of the hook initialization

### withSharedHooks(hooks)(Component)
- `hooks`: *object* - object of created hooks
- `Component`: *React Component* - wrapped component

### useSharedHook(selector)
- `selector`: *function* - selector function that receives object of all hooks

## Examples

* Simple `useState` - https://codesandbox.io/s/9zy9jwkyj4
* Inputs - https://codesandbox.io/s/kw43p7m0vr
* With `useReducer` - https://codesandbox.io/s/7yrzn42w8x
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "react-shared-hooks",
"version": "0.0.1",
"description": "React shared hooks",
"main": "dist/index.js",
"repository": "https://github.com/dimapaloskin/react-shared-hooks",
"author": "Dima Paloskin",
"license": "MIT",
"scripts": {
"build": "rollup -c rollup.config.js",
"lint": "eslint ./src"
},
"devDependencies": {
"@babel/core": "^7.1.5",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.8.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-flowtype": "^3.2.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jest": "^22.0.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-react": "^7.11.1",
"eslint-plugin-standard": "^4.0.0",
"rollup": "^0.67.0",
"rollup-plugin-babel": "^4.0.3"
},
"peerDependencies": {
"react": "^16.7.0-alpha.0"
}
}
13 changes: 13 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import babel from 'rollup-plugin-babel';

const lib = {
input: 'src/index.js',
output: {
file: 'dist/index.js',
format: 'cjs',
sourcemap: 'inline'
},
plugins: [ babel() ]
};

export default [lib]
7 changes: 7 additions & 0 deletions src/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @flow

import * as React from 'react'

const GlobalContext: React.Context<{}> = React.createContext({})

export default GlobalContext
50 changes: 50 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// @flow

import * as React from 'react'
import GlobalContext from './context'

// $FlowFixMe
const { useContext } = React

type SharedHook = {
Context: React.Context<*>,
Provider: React.ComponentType<{ children: React.Node }>,
}

export const createSharedHook = (useHook: Function, ...args: any[]) => {
const Context: React.Context<*> = React.createContext(null)

const Provider = (props: { children: React.Node }) => {
const result = useHook(...args)

return <Context.Provider value={result}>{props.children}</Context.Provider>
}

return {
Context,
Provider,
}
}

export const useSharedHook = (selector: Function) => {
const globalContext = useContext(GlobalContext)
const sharedHook = selector(globalContext.hooks)
const result = useContext(sharedHook.Context)
return result
}

export const withSharedHooks = (hooks: { [key: any]: SharedHook }) => (
Component: React.ComponentType<*>,
) => {
const hooksArray: Array<SharedHook> = Object.keys(hooks).map(key => hooks[key])

const GlobalSharedHooksProvider = (props: *) => {
const nestedProviders = hooksArray.reduce((acc, { Provider }) => {
return <Provider>{acc}</Provider>
}, <Component {...props} />)

return <GlobalContext.Provider value={{ hooks }}>{nestedProviders}</GlobalContext.Provider>
}

return GlobalSharedHooksProvider
}
Empty file added tests/empty
Empty file.
Loading

0 comments on commit 7ee3ddc

Please sign in to comment.