Skip to content

Commit

Permalink
More progress on core functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
spautz committed Jul 26, 2020
1 parent eadafcd commit 3cbd17a
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 79 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ together in a component.
This library is useful for accessing Redux state from _within_ a Recoil selector -- which lets you call selectors
conditionally, or within loops. `useSelector` can't do that.

This library can help you avoid unnecessary rerenders in some situations. It can also facilitate a migration from
Redux to Recoil.
It can also facilitate a migration from Redux to Recoil.

## Performance notes

Until [Recoil issue #314](https://github.com/facebookexperimental/Recoil/issues/314) is worked, each component that
uses a Redux-linked atom or selector will rerender when Redux updates.

## Roadmap

Expand Down
2 changes: 1 addition & 1 deletion demos/todo-list/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"react-scripts": "3.4.1",
"recoil": "^0.0.10",
"redux": "^4.0.5",
"redux-to-recoil": "file:../../",
"redux-to-recoil": "../../",
"reselect": "^4.0.0"
},
"scripts": {
Expand Down
5 changes: 3 additions & 2 deletions demos/todo-list/src/components.recoil/VisibleTodoList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import { toggleTodo } from '../actions';
import getVisibleTodos from '../selectors/getVisibleTodos';
import Todo from './Todo';

const todosSelector = selectorFromReselect(getVisibleTodos);
// const todosSelector = selectorFromReselect(getVisibleTodos);

const VisibleTodoList = (props) => {
const dispatch = useDispatch();

const todos = useRecoilValue(todosSelector);
// console.log()
const todos = []; //useRecoilValue(todosSelector);

return (
<ul>
Expand Down
20 changes: 1 addition & 19 deletions demos/todo-list/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8850,11 +8850,6 @@ realpath-native@^1.1.0:
dependencies:
util.promisify "^1.0.0"

recoil@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/recoil/-/recoil-0.0.10.tgz#679ab22306f559f8a63c46fd5ff5241539f9248f"
integrity sha512-+9gRqehw3yKETmoZbhSnWu4GO10HDb5xYf1CjLF1oXGK2uT6GX5Lu9mfTXwjxV/jXxEKx8MIRUUbgPxvbJ8SEw==

recursive-readdir@2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f"
Expand All @@ -8870,17 +8865,9 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"

"redux-to-recoil@file:../..":
"redux-to-recoil@file:../redux-to-recoil":
version "0.0.1"

redux@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"

regenerate-unicode-properties@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
Expand Down Expand Up @@ -10001,11 +9988,6 @@ svgo@^1.0.0, svgo@^1.2.2:
unquote "~1.1.1"
util.promisify "~1.0.0"

symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==

symbol-tree@^3.2.2:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"devDependencies": {
"@types/jest": "^26.0.7",
"@types/react": "^16.9.43",
"@types/react-redux": "^7.1.9",
"@typescript-eslint/eslint-plugin": "^3.7.0",
"@typescript-eslint/parser": "^3.7.0",
"coveralls": "^3.1.0",
Expand All @@ -78,6 +79,8 @@
"yarn-or-npm": "^3.0.1"
},
"peerDependencies": {
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-redux": "^7.0.0",
"recoil": "^0.0.10",
"redux": "^4.0.5"
Expand Down
18 changes: 13 additions & 5 deletions src/SyncReduxToRecoil.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { useEffect } from 'react';
import React from 'react';
import { useSelector } from 'react-redux';
import { useRecoilState } from 'recoil';

import { reduxStateAtom } from './internals';

const selectEntireState = (state: any) => state;

interface SyncReduxToRecoilProps {
enabled?: boolean;
Expand All @@ -7,11 +13,13 @@ interface SyncReduxToRecoilProps {
const SyncReduxToRecoil: React.FC<SyncReduxToRecoilProps> = (props) => {
const { children, enabled } = props;

// const reduxStore = useSt();
const [lastReduxState, setReduxState] = useRecoilState(reduxStateAtom);

useEffect(() => {
console.log('SyncReduxToRecoil:useEffect');
}, [enabled]);
const currentReduxState = useSelector(selectEntireState);
if (enabled && currentReduxState !== lastReduxState) {
console.log('new currentReduxState!', currentReduxState);
setReduxState(currentReduxState);
}

return <React.Fragment>{children}</React.Fragment>;
};
Expand Down
10 changes: 5 additions & 5 deletions src/atomFromRedux.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { RecoilState, selector } from 'recoil';

import { getReduxSourceAtom, getValueAtPath } from './util';
import { getValueAtPath, reduxStateAtom } from './internals';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const atomFromRedux = <ReturnType = any>(namespace: string): RecoilState<ReturnType> => {
Expand All @@ -9,11 +9,11 @@ const atomFromRedux = <ReturnType = any>(namespace: string): RecoilState<ReturnT

// Although named "atomFromRedux", each instance is actually just a selector. They all pull from a single atom
const selectorFromRedux = selector<ReturnType>({
key: `redux-to-recoil:${namespaceParts.join('.')}`,
key: `redux-to-recoil:atom:${namespaceParts.join('.')}`,
get: ({ get }) => {
const reduxSourceAtom = getReduxSourceAtom();
const reduxState = get(reduxSourceAtom);
return getValueAtPath(reduxState, namespaceParts);
const reduxState = get(reduxStateAtom);
const value = getValueAtPath(reduxState, namespaceParts);
return value;
},
set: ({ get, set }) => {
console.log('TODO: Bidirectional support', namespace, { get, set });
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export * from './atomFromRedux';

export { default as selectorFromReselect } from './selectorFromReselect';
export * from './selectorFromReselect';

export * as internals from './internals';
17 changes: 17 additions & 0 deletions src/internals/getValueAtPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const getValueAtPath = (state: any, pathParts: Array<string>): any => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let currentResult = state;
let i = 0;
while (currentResult && i < pathParts.length) {
currentResult = currentResult[pathParts[i]];
i++;
}

if (i === pathParts.length) {
return currentResult;
}
return undefined;
};

export default getValueAtPath;
5 changes: 5 additions & 0 deletions src/internals/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { default as getValueAtPath } from './getValueAtPath';
export * from './getValueAtPath';

export { default as reduxStateAtom } from './reduxStateAtom';
export * from './reduxStateAtom';
8 changes: 8 additions & 0 deletions src/internals/reduxStateAtom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { atom } from 'recoil';

const reduxStateAtom = atom({
key: 'redux-to-recoil:state',
default: null,
});

export default reduxStateAtom;
26 changes: 23 additions & 3 deletions src/selectorFromReselect.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
const selectorFromReselect = (): null => {
console.log('selectorFromReselect: not implemented');
return null;
import { RecoilValueReadOnly, selector } from 'recoil';

import { reduxStateAtom } from './internals';

let count = 0;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const selectorFromReselect = <ReturnType = any>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
selectorFn: (reduxState: any) => ReturnType,
): RecoilValueReadOnly<ReturnType> => {
count++;

const wrappedSelector = selector<ReturnType>({
key: `redux-to-recoil:selector:${count}${selectorFn.name}`,
get: ({ get }) => {
const reduxState = get(reduxStateAtom);
const value = selectorFn(reduxState);
return value;
},
});

return wrappedSelector;
};

export default selectorFromReselect;
40 changes: 0 additions & 40 deletions src/util.ts

This file was deleted.

22 changes: 20 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,14 @@
dependencies:
"@types/node" "*"

"@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"

"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
Expand Down Expand Up @@ -1275,7 +1283,17 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==

"@types/react@^16.9.43":
"@types/react-redux@^7.1.9":
version "7.1.9"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.9.tgz#280c13565c9f13ceb727ec21e767abe0e9b4aec3"
integrity sha512-mpC0jqxhP4mhmOl3P4ipRsgTgbNofMRXJb08Ms6gekViLj61v1hOZEKWDCyWsdONr6EjEA6ZHXC446wdywDe0w==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"

"@types/react@*", "@types/react@^16.9.43":
version "16.9.43"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b"
integrity sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg==
Expand Down Expand Up @@ -6301,7 +6319,7 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"

redux@^4.0.5:
redux@^4.0.0, redux@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
Expand Down

0 comments on commit 3cbd17a

Please sign in to comment.