Skip to content


Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


Read and write your Redux store through Recoil.

npm version build status test coverage dependencies status gzip size


atomFromRedux creates a Recoil wrapper around a location in Redux. This works like any other atom.

import { selector, useRecoilState, useRecoilValue } from 'recoil';
import { atomFromRedux } from 'redux-to-recoil';

const todosAtom = atomFromRedux('.todos'); // wraps state.todos

// Inside your component, use the atoms and selectors as normal. That's it.
const [todos, setTodos] = useRecoilState(todosAtom);

// Also: it's a normal Recoil atom, so it works in Recoil selectors
const todoCountSelector = selector({
  key: 'todoCount',
  get: ({ get }) => get(todosAtom).length,
const todoCount = useRecoilValue(todoCountSelector);

<SyncReduxToRecoil /> syncs state from Redux to Recoil. This is required.

import { SyncReduxToRecoil } from 'redux-to-recoil';

<Provider store={store}>
    <SyncReduxToRecoil />
    <MyApp />

selectorFromReselect creates a Recoil selector from a plain selector, using Reselect or any other selector library.

import { selectorFromReselect, useRecoilValue } from 'recoil';

const todosSelector = selectorFromReselect((state) => state.todos);

// Inside your component, use the selector as normal. That's it.
const [todos, setTodos] = useRecoilState(todosAtom);

// Also: it's a normal Recoil selector, so it works in other Recoil selectors
const todoCountSelector = selector({
  key: 'todoCount',
  get: ({ get }) => get(todosSelector).length,
const todoCount = useRecoilValue(todoCountSelector);

If you want to dispatch changes from Recoil back to Redux then wrap your reducer with syncChangesFromRecoil and enable the writeEnabled option. This is only needed if you set Recoil values directly.

import { syncChangesFromRecoil } from 'redux-to-recoil';

// This will enable write-from-recoil (when options.writeEnabled is turned on)
const reducer = syncChangesFromRecoil(yourRootReducer);
const store = createStore(reducer);
//  Recoil atoms and writeable selectors work like normal
const todosAtom = atomFromRedux('.todos');

const [todos, setTodos] = useRecoilState(todosAtom);


Do I need this?

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.

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. (Dynamic-Selectors can, though.)

It can also facilitate a migration from Redux to Recoil.


Options are available to control how and whether Recoil receives updates from, and writes updates to, Redux.


A Todo List demo shows both a read-only sync from redux and a read-write sync.

Recoil version compatibility

Recoil Redux-to-Recoil
0.7.0 0.8.x
0.6.x 0.8.x
0.5.x 0.7.1-0.8.x
0.4.x 0.6.0-0.7.1
0.3.x 0.5.1-0.6.0
0.2.x 0.4.1-0.5.1
0.1.x 0.4.1
0.0.13 0.3.1
0.0.10 0.2.2

Other versions of Recoil and Redux-to-Recoil may be compatible: this table just lists the thoroughly tested pairings.