diff --git a/.prettierignore b/.prettierignore index 764f24e..cf0f6e7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,6 +12,7 @@ !**/*.tsx # Unless they're somewhere we can ignore +build/ dist/ coverage/ node_modules/ diff --git a/README.md b/README.md index 16ccf14..fcd504b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Redux-to-Recoil -Create Recoil atoms and selectors from your existing actions, reducers, and selectors +Access your Redux store through Recoil atoms and selectors. **This package is in active development. Things will change rapidly, and it is not yet production-ready. Feedback is welcome.** @@ -9,72 +9,56 @@ Create Recoil atoms and selectors from your existing actions, reducers, and sele [![test coverage](https://img.shields.io/coveralls/github/spautz/redux-to-recoil.svg)](https://coveralls.io/github/spautz/redux-to-recoil) [![gzip size](https://img.shields.io/bundlephobia/minzip/redux-to-recoil)](https://bundlephobia.com/result?p=redux-to-recoil) -## Motivation +## Example -Migrating from [Redux](https://redux.js.org/) to [Recoil](https://recoiljs.org/) can be a lot of work. - -This library contains utilities which take in your existing Redux-oriented functions and return Recoil state. -The goal is to try things out with Recoil without having to migrate your entire codebase first. - -## How it works - -There are two different sets of helpers: - -`atomFromReduxState` lets you access your existing Redux state through Recoil. Data is still stored in Redux. - -`createAtomFactory`, `dispatchToRecoil`, and `wrapSelector` let you use your existing Redux-oriented code to manufacture Recoil atoms and -selectors. All data is stored in Recoil. - -## Examples +Use `atomFromRedux` to create a Recoil wrapper around a location in Redux. This works exactly like any other atom or +selector. ```typescript jsx -import { selector, useRecoilState } from 'recoil'; -import { atomFromReduxState } from 'redux-to-recoil'; -import { myActionCreator, myReducer, mySelector } from 'my-existing-code'; +import { selector, useRecoilState, useRecoilValue } from 'recoil'; +import { atomFromRedux } from 'redux-to-recoil'; -// `atomFromReduxState` replaces Recoil's `atom()` constructor -const todoListAtom = atomFromReduxState('.todos'); // wraps state.todos +const todosAtom = atomFromRedux('.todos'); // wraps state.todos const todoCountSelector = selector({ key: 'todoCount', - get: ({ get }) => get(todoList).length, + get: ({ get }) => get(todosAtom).length, }); // Inside your component, use the atoms and selectors as normal -const [todoList, setTodoList] = useRecoilState(todoListAtom); -const todoCount = useRecoilState(todoCountSelector); - -// All Redux middleware and tools still work +const [todos, setTodos] = useRecoilState(todosAtom); +const todoCount = useRecoilValue(todoCountSelector); ``` +A redux-to-recoil provider syncs state between the two stores. + ```typescript jsx -import { useRecoilState } from 'recoil'; -import { createAtomFactory, useRecoilDispatch, useRecoilSelector } from 'redux-to-recoil'; -import { addTodo, editTodo, todosReducer, todosSelector } from 'my-existing-code'; +import { SyncReduxToRecoil } from 'redux-to-recoil'; + + + + + + +; +``` -const createTodoAtom = createAtomFactory({ - namespace: 'todos', - reducer: todosReducer, -}); +## Do I need this? -const todoAtom = createTodoAtom('.'); // represents state.todos -const todoCountAtom = createTodoAtom('.length'); // represents state.todos.length +You probably don't need this. Redux and Recoil work fine side-by-side. You can already use values from Redux and Recoil +together in a component. -// Inside your component, use the atoms and selectors as normal -const [todos, setTodos] = useRecoilState(todoAtom); -const todoCount = useRecoilState(todoCountAtom); +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. -// `useDispatch` becomes `useRecoilDispatch`, `useSelector` becomes `useRecoilSelector` -const todoCount = useRecoilSelector(todosSelector); - + ); +}; + +const mapStateToProps = (state, ownProps) => ({ + active: ownProps.filter === state.visibilityFilter, +}); + +const mapDispatchToProps = (dispatch, ownProps) => ({ + onClick: () => dispatch(setVisibilityFilter(ownProps.filter)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(FilterLink); diff --git a/demos/todo-list/src/components.recoil/Todo.jsx b/demos/todo-list/src/components.recoil/Todo.jsx new file mode 100644 index 0000000..7aa8c8f --- /dev/null +++ b/demos/todo-list/src/components.recoil/Todo.jsx @@ -0,0 +1,2 @@ +// Because Todo doesn't read from the store, it's the same between Redux and Redux-to-Recoil +export { default } from '../components.redux/Todo'; diff --git a/demos/todo-list/src/components/VisibleTodoList.jsx b/demos/todo-list/src/components.recoil/VisibleTodoList.jsx similarity index 77% rename from demos/todo-list/src/components/VisibleTodoList.jsx rename to demos/todo-list/src/components.recoil/VisibleTodoList.jsx index b30cbfe..36aefcc 100644 --- a/demos/todo-list/src/components/VisibleTodoList.jsx +++ b/demos/todo-list/src/components.recoil/VisibleTodoList.jsx @@ -2,13 +2,13 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { toggleTodo } from '../actions'; -import visibleTodosSelector from '../selectors/visibleTodosSelector'; +import getVisibleTodos from '../selectors/getVisibleTodos'; import Todo from './Todo'; const VisibleTodoList = (props) => { const dispatch = useDispatch(); - const todos = useSelector(visibleTodosSelector); + const todos = useSelector(getVisibleTodos); return (