├── tsconfig.json ├── src └── index.tsx ├── tslint.json ├── package.json ├── README.md └── .gitignore /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "lib", 4 | "sourceMap": true, 5 | "noImplicitAny": true, 6 | "module": "commonjs", 7 | "target": "es5", 8 | "jsx": "react", 9 | "allowJs": true, 10 | "esModuleInterop": true, 11 | "moduleResolution": "node", 12 | "experimentalDecorators": true, 13 | "lib": [ 14 | "dom", 15 | "es5", 16 | "es6", 17 | "scripthost", 18 | "es2015.core", 19 | "es2015.promise" 20 | ] 21 | }, 22 | "include": [ 23 | "src/**/*" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Store, createStoreObject } from 'effector'; 3 | import { createStoreConsumer } from 'effector-react'; 4 | 5 | type GetInnerType = S extends Store ? T : never; 6 | 7 | export type Injected = Partial<{ 8 | [key in K]: GetInnerType; 9 | }>; 10 | 11 | export function inject( 12 | stores: {[key in K]: Store}, 13 | ): any { 14 | const merged = createStoreObject(stores); 15 | const Consumer = createStoreConsumer(merged); 16 | 17 | return ( 18 | Cmp: React.ComponentType, 19 | ) => (props: Props & {[key in K]: typeof stores[key]}) => ( 20 | 21 | {state => } 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint:latest", 4 | "tslint-react" 5 | ], 6 | "rules": { 7 | "jsx-no-multiline-js": false, 8 | "no-console": false, 9 | "no-implicit-dependencies": false, 10 | "no-var-requires": false, 11 | "jsx-boolean-value": false, 12 | "no-submodule-imports": false, 13 | "no-trailing-whitespace": true, 14 | "no-consecutive-blank-lines": [true], 15 | "semicolon": [true, "always"], 16 | "max-line-length": [true, { "limit": 120, "ignore-pattern": "//"}], 17 | "variable-name": ["check-format", "allow-leading-underscore"], 18 | "quotemark": [ 19 | true, 20 | "single", 21 | "avoid-escape", 22 | "jsx-double" 23 | ], 24 | "member-ordering": false, 25 | "ban-types": false, 26 | "no-eval": true, 27 | "ordered-imports": false, 28 | "object-literal-sort-keys": false, 29 | "arrow-parens": false 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "effector-react-inject", 3 | "version": "0.1.5", 4 | "description": "effector-react-inject", 5 | "main": "lib/index.js", 6 | "files": [ 7 | "lib" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/today-/effector-react-inject.git" 12 | }, 13 | "scripts": { 14 | "test": "tslint -c tslint.json src/**/*.ts?", 15 | "build": "./node_modules/.bin/tsc" 16 | }, 17 | "types": "./lib/index.d.ts", 18 | "author": "today- (https://github.com/today-)", 19 | "license": "ISC", 20 | "keywords": [ 21 | "effector", 22 | "inject", 23 | "connect", 24 | "react", 25 | "redux", 26 | "state" 27 | ], 28 | "homepage": "https://github.com/today-/effector-react-inject", 29 | "dependencies": { 30 | "effector": "^0.18.2", 31 | "effector-react": "^0.18.6" 32 | }, 33 | "devDependencies": { 34 | "@types/react": "^16.8.6", 35 | "typescript": "^3.3.0", 36 | "tslint": "^5.17.0", 37 | "tslint-loader": "^3.5.4", 38 | "tslint-react": "^3.6.0" 39 | }, 40 | "peerDependencies": { 41 | "effector": "^0.18.2", 42 | "effector-react": "^0.18.6", 43 | "react": "^0.13.0 || ^0.14.0 || ^15.0.0 || ^16.0.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Effector-react-inject 2 | 3 | Inject [Effector](https://github.com/zerobias/effector)'s state to React components simple way 4 | 5 | ## Usage 6 | 7 | #### Connecting to React components 8 | 9 | ```jsx harmony 10 | 11 | export const Todos = inject({ todos, user })(TodoList); 12 | ``` 13 | 14 | `TodoList` component then will receive `todos` and `user` props with state from `todos` and `user` effector stores respectively. 15 | 16 | #### Connecting to React class components using decorators 17 | 18 | ```jsx harmony 19 | @inject({ todos, user }) 20 | export class TodoList extends React.Component { 21 | ``` 22 | 23 | [Babel decorators](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy) 24 | 25 | [TypeScript decorators](https://www.typescriptlang.org/docs/handbook/decorators.html) 26 | 27 | #### TypeScript declarations 28 | 29 | ```typescript jsx 30 | import { inject, Injected } from 'effector-react-inject'; 31 | 32 | const stores = { todos, user }; 33 | 34 | type TodoListProps = OwnProps & Injected; 35 | 36 | class TodoList extends React.Component { 37 | ``` 38 | 39 | ### Motivation 40 | 41 | - Classic `redux-connect`-like HOC syntax, can be easily composed. 42 | 43 | - Less dependent on Effector's core API, especially if injecting multiple stores. 44 | 45 | - Can be used as a decorator for React class components 46 | 47 | - Wrappable components can be tested separately 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,windows,linux,macos 3 | 4 | ### Linux ### 5 | *~ 6 | 7 | # temporary files which can be created if a process still has a handle open of a deleted file 8 | .fuse_hidden* 9 | 10 | # KDE directory preferences 11 | .directory 12 | 13 | # Linux trash folder which might appear on any partition or disk 14 | .Trash-* 15 | 16 | # .nfs files are created when an open file is removed but is still being accessed 17 | .nfs* 18 | 19 | ### macOS ### 20 | *.DS_Store 21 | .AppleDouble 22 | .LSOverride 23 | 24 | # Icon must end with two \r 25 | Icon 26 | 27 | # Thumbnails 28 | ._* 29 | 30 | # Files that might appear in the root of a volume 31 | .DocumentRevisions-V100 32 | .fseventsd 33 | .Spotlight-V100 34 | .TemporaryItems 35 | .Trashes 36 | .VolumeIcon.icns 37 | .com.apple.timemachine.donotpresent 38 | 39 | # Directories potentially created on remote AFP share 40 | .AppleDB 41 | .AppleDesktop 42 | Network Trash Folder 43 | Temporary Items 44 | .apdisk 45 | 46 | ### Node ### 47 | # Logs 48 | logs 49 | *.log 50 | npm-debug.log* 51 | yarn-debug.log* 52 | yarn-error.log* 53 | .idea 54 | .vscode 55 | 56 | # Runtime data 57 | pids 58 | *.pid 59 | *.seed 60 | *.pid.lock 61 | 62 | # Directory for instrumented libs generated by jscoverage/JSCover 63 | lib-cov 64 | 65 | # Coverage directory used by tools like istanbul 66 | coverage 67 | 68 | # nyc test coverage 69 | .nyc_output 70 | 71 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 72 | .grunt 73 | 74 | # Bower dependency directory (https://bower.io/) 75 | bower_components 76 | 77 | # node-waf configuration 78 | .lock-wscript 79 | 80 | # Compiled binary addons (http://nodejs.org/api/addons.html) 81 | build/Release 82 | 83 | # Dependency directories 84 | node_modules/ 85 | jspm_packages/ 86 | 87 | # Typescript v1 declaration files 88 | typings/ 89 | 90 | # Optional npm cache directory 91 | .npm 92 | 93 | # Optional eslint cache 94 | .eslintcache 95 | 96 | # Optional REPL history 97 | .node_repl_history 98 | 99 | # Output of 'npm pack' 100 | *.tgz 101 | 102 | # Yarn Integrity file 103 | .yarn-integrity 104 | 105 | # dotenv environment variables file 106 | .env 107 | 108 | 109 | ### Windows ### 110 | # Windows thumbnail cache files 111 | Thumbs.db 112 | ehthumbs.db 113 | ehthumbs_vista.db 114 | 115 | # Folder config file 116 | Desktop.ini 117 | 118 | # Recycle Bin used on file shares 119 | $RECYCLE.BIN/ 120 | 121 | # Windows Installer files 122 | *.cab 123 | *.msi 124 | *.msm 125 | *.msp 126 | 127 | # Windows shortcuts 128 | *.lnk 129 | 130 | 131 | # End of https://www.gitignore.io/api/node,windows,linux,macos 132 | lib/* 133 | --------------------------------------------------------------------------------