diff --git a/README.md b/README.md index 5d88ffb..4dfa878 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,6 @@ React 16.13. This does not hurt anything, but it is annoying. - [x] Core functionality: atomFromRedux - [x] Core functionality: selectorFromReselect - [ ] Tests -- [x] Core functionality: middleware for writing back to redux +- [ ] Core functionality: middleware for writing back to redux - [x] Demo - [ ] Initial release diff --git a/demos/todo-list/package.json b/demos/todo-list/package.json index 3f23c58..a26f570 100644 --- a/demos/todo-list/package.json +++ b/demos/todo-list/package.json @@ -12,7 +12,7 @@ "react-scripts": "3.4.1", "recoil": "^0.0.10", "redux": "^4.0.5", - "redux-to-recoil": "github:spautz/redux-to-recoil#master", + "redux-to-recoil": "latest", "reselect": "^4.0.0" }, "scripts": { diff --git a/demos/todo-list/src/App.recoil-readonly.jsx b/demos/todo-list/src/App.recoil-readonly.jsx index 626a990..716bb3c 100644 --- a/demos/todo-list/src/App.recoil-readonly.jsx +++ b/demos/todo-list/src/App.recoil-readonly.jsx @@ -7,9 +7,7 @@ import VisibleTodoList from './components-recoil-readonly/VisibleTodoList'; const RecoilReadOnlyApp = () => (
- - Redux-to-Recoil: Read-only - + Redux-to-Recoil: Read-only diff --git a/demos/todo-list/src/App.recoil-readwrite.jsx b/demos/todo-list/src/App.recoil-readwrite.jsx index deac087..e72aa9b 100644 --- a/demos/todo-list/src/App.recoil-readwrite.jsx +++ b/demos/todo-list/src/App.recoil-readwrite.jsx @@ -7,9 +7,7 @@ import VisibleTodoList from './components-recoil-readwrite/VisibleTodoList'; const RecoilReadWriteApp = () => (
- - Redux-to-Recoil: Read-Write (with middleware) - + Redux-to-Recoil: Read-Write (with middleware) diff --git a/demos/todo-list/src/components-recoil-readwrite/VisibleTodoList.jsx b/demos/todo-list/src/components-recoil-readwrite/VisibleTodoList.jsx index 68a0b3e..371607d 100644 --- a/demos/todo-list/src/components-recoil-readwrite/VisibleTodoList.jsx +++ b/demos/todo-list/src/components-recoil-readwrite/VisibleTodoList.jsx @@ -9,7 +9,7 @@ const todosAtom = atomFromRedux('.todos'); const VisibleTodoList = () => { const [, setAllTodos] = useRecoilState(todosAtom); - const [todos, updateTodos] = useRecoilState(getVisibleTodos); + const [todos] = useRecoilState(getVisibleTodos); const toggleTodo = (id) => { setAllTodos((allTodos) => diff --git a/demos/todo-list/yarn.lock b/demos/todo-list/yarn.lock index 65a5d1c..8c27c25 100644 --- a/demos/todo-list/yarn.lock +++ b/demos/todo-list/yarn.lock @@ -1572,6 +1572,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== +"@types/lodash@^4.14.158": + version "4.14.158" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.158.tgz#b38ea8b6fe799acd076d7a8d7ab71c26ef77f785" + integrity sha512-InCEXJNTv/59yO4VSfuvNrZHt7eeNtWQEgnieIA+mIC+MOWM9arOWG2eQ8Vhk6NbOre6/BidiXhkZYeDY9U35w== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -8875,9 +8880,14 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -"redux-to-recoil@github:spautz/redux-to-recoil#dev--core-functionality": +redux-to-recoil@latest: version "0.0.1" - resolved "https://codeload.github.com/spautz/redux-to-recoil/tar.gz/3cbd17af6a4ea4875ad74fa6f7cbea49265f5de8" + resolved "https://registry.yarnpkg.com/redux-to-recoil/-/redux-to-recoil-0.0.1.tgz#3f123c701bb4f04e41174693024d98a0df2a02d7" + integrity sha512-vFmo+rVW/0rriEHUFbCcCed4oMi3XlxFKRUvy36+nvGW2KbO9pzQxeUnrivE48rZf56qYpp8lPMSdmd59HGLxw== + dependencies: + "@types/lodash" "^4.14.158" + limited-cache "^0.5.0" + lodash "^4.17.19" redux@^4.0.5: version "4.0.5" diff --git a/package.json b/package.json index 26eaeba..de05ae9 100644 --- a/package.json +++ b/package.json @@ -49,9 +49,7 @@ "types": "tsc --noEmit --p tsconfig.json" }, "dependencies": { - "@types/lodash": "^4.14.158", - "limited-cache": "^0.5.0", - "lodash": "^4.17.19" + "@ngard/tiny-get": "^1.2.2" }, "devDependencies": { "@types/jest": "^26.0.7", diff --git a/src/SyncReduxToRecoil.tsx b/src/SyncReduxToRecoil.tsx index 6f18d52..bcc843a 100644 --- a/src/SyncReduxToRecoil.tsx +++ b/src/SyncReduxToRecoil.tsx @@ -3,8 +3,9 @@ import { useSelector } from 'react-redux'; import { useRecoilState } from 'recoil'; import internalStateAtom from './internalStateAtom'; +import { ReduxState } from './types'; -const selectEntireState = (state: any) => state; +const selectEntireState = (state: ReduxState) => state; interface SyncReduxToRecoilProps { enabled?: boolean; diff --git a/src/atomFromRedux.ts b/src/atomFromRedux.ts index 07cd3e4..ebb7620 100644 --- a/src/atomFromRedux.ts +++ b/src/atomFromRedux.ts @@ -1,19 +1,19 @@ -import getPath from 'lodash/get'; +import { get as getPath } from '@ngard/tiny-get'; import { RecoilState, selector } from 'recoil'; -import { LimitedCache } from 'limited-cache'; import internalStateAtom from './internalStateAtom'; +import { DefaultReturnType } from './types'; -const atomSelectorCache = LimitedCache(); +const atomSelectorCache = Object.create(null); +const { hasOwnProperty } = Object.prototype; // This works similarly to Recoil's atomFamily/selectorFamily, except we de-dupe things by path, and don't keep // old selectors around for forever. -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const atomFromRedux = (path: string): RecoilState => { +const atomFromRedux = (path: string): RecoilState => { // The leading dot is just a convention to make things easier to read const realPath = path.charAt(0) === '.' ? path.substr(1) : path; - if (!atomSelectorCache.has(realPath)) { + if (!hasOwnProperty.call(atomSelectorCache, realPath)) { console.log('creating selector for path: ', realPath); // Although named "atomFromRedux", each instance is actually just a selector. They all pull from a single atom. @@ -31,10 +31,10 @@ const atomFromRedux = (path: string): RecoilState }, }); - atomSelectorCache.set(realPath, selectorForPath); + atomSelectorCache[realPath] = selectorForPath; } - return atomSelectorCache.get(realPath); + return atomSelectorCache[realPath]; }; export default atomFromRedux; diff --git a/src/internalStateAtom.ts b/src/internalStateAtom.ts index 48b48c8..1a1c921 100644 --- a/src/internalStateAtom.ts +++ b/src/internalStateAtom.ts @@ -1,7 +1,8 @@ import { atom } from 'recoil'; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const internalStateAtom = atom({ +import { ReduxState } from './types'; + +const internalStateAtom = atom({ key: 'redux-to-recoil:state', default: null, }); diff --git a/src/selectorFromReselect.ts b/src/selectorFromReselect.ts index 97fb33f..6e83fc8 100644 --- a/src/selectorFromReselect.ts +++ b/src/selectorFromReselect.ts @@ -1,13 +1,12 @@ import { RecoilValueReadOnly, selector } from 'recoil'; import internalStateAtom from './internalStateAtom'; +import { DefaultReturnType, ReduxState } from './types'; let count = 0; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const selectorFromReselect = ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - selectorFn: (reduxState: any) => ReturnType, +const selectorFromReselect = ( + selectorFn: (reduxState: ReduxState) => ReturnType, ): RecoilValueReadOnly => { count++; diff --git a/src/typeDeclarations.d.ts b/src/typeDeclarations.d.ts new file mode 100644 index 0000000..5f32bb8 --- /dev/null +++ b/src/typeDeclarations.d.ts @@ -0,0 +1,7 @@ +// Microbundle handles this +declare const __DEV__: boolean; + +declare module '@ngard/tiny-get' { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + export function get(object: any, path: string | Array, defaultValue?: any): any; +} diff --git a/src/types.ts b/src/types.ts index 22ecbeb..41749c9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,2 +1,4 @@ -// Microbundle manages this: it's not a real variable -declare const __DEV__: boolean; +// These renames are for readability, and to avoid having to repeatedly disable no-explicit-any when used. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type DefaultReturnType = any; +export type ReduxState = unknown; diff --git a/yarn.lock b/yarn.lock index 375f0cc..cb817a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1078,6 +1078,11 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@ngard/tiny-get@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@ngard/tiny-get/-/tiny-get-1.2.2.tgz#3784ea1fdd852a59a44d50c144f070529422d7a7" + integrity sha512-+B2yx8KGWPxi/z0fqCgA+gNEWGwoVJZ8v98DFHIEVtEfn5BHXV8Wcr9NfracmrZa2dqekyXduPFcw2sL1HUw6Q== + "@rollup/plugin-alias@^3.1.1": version "3.1.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.1.tgz#bb96cf37fefeb0a953a6566c284855c7d1cd290c" @@ -1248,11 +1253,6 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== -"@types/lodash@^4.14.158": - version "4.14.158" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.158.tgz#b38ea8b6fe799acd076d7a8d7ab71c26ef77f785" - integrity sha512-InCEXJNTv/59yO4VSfuvNrZHt7eeNtWQEgnieIA+mIC+MOWM9arOWG2eQ8Vhk6NbOre6/BidiXhkZYeDY9U35w== - "@types/minimist@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" @@ -4716,11 +4716,6 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -limited-cache@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/limited-cache/-/limited-cache-0.5.0.tgz#5e10e875e7c1e1bdae74881852bf93482c441bc7" - integrity sha512-ozZr9n273zQTmxr5YiecChUo8vEbJW49jsuER9sZNAdjiCzhTE58eOWbA47/iYKu6OCPVNQ2dWs8O6zBgMeYxg== - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"