forked from pmndrs/jotai
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: jotai/redux * add build script * add example * Update docs/api/redux.md Co-authored-by: Mathis Møller <[email protected]> Co-authored-by: Mathis Møller <[email protected]>
- Loading branch information
Showing
7 changed files
with
447 additions
and
283 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
This doc describes `jotai/redux` bundle. | ||
|
||
Jotai's state resides in React, but sometimes it would be nice | ||
to intract with the world outside React. | ||
Redux provides a store interface that can be used to store some values | ||
and sync with atoms in jotai. | ||
|
||
## Install | ||
|
||
You have to install `redux` to access this bundle and its functions. | ||
|
||
``` | ||
npm install redux | ||
# or | ||
yarn add redux | ||
``` | ||
|
||
## atomWithStore | ||
|
||
`atomWithStore` creates a new atom with redux store. | ||
It's two-way binding and you can change the value from both ends. | ||
|
||
```js | ||
import { useAtom } from 'jotai' | ||
import { atomWithStore } from 'jotai/redux' | ||
import { createStore } from 'redux' | ||
|
||
const initialState = { count: 0 } | ||
const reducer = (state = initialState, action: { type: 'INC' }) => { | ||
if (action.type === 'INC') { | ||
return { ...state, count: state.count + 1 } | ||
} | ||
return state | ||
} | ||
const store = createStore(reducer) | ||
const storeAtom = atomWithStore(store) | ||
|
||
const Counter: React.FC = () => { | ||
const [state, dispatch] = useAtom(storeAtom) | ||
|
||
return ( | ||
<> | ||
count: {state.count} | ||
<button onClick={() => dispatch({ type: 'INC' })}>button</button> | ||
</> | ||
) | ||
} | ||
``` | ||
|
||
### Examples | ||
|
||
https://codesandbox.io/s/react-typescript-forked-cmlu5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { atomWithStore } from './redux/atomWithStore' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import type { Store, Action, AnyAction } from 'redux' | ||
import { atom } from 'jotai' | ||
import type { NonFunction } from '../core/types' | ||
|
||
export function atomWithStore<State, A extends Action = AnyAction>( | ||
store: Store<State, A> | ||
) { | ||
const baseAtom = atom(store.getState() as NonFunction<State>) | ||
baseAtom.onMount = (setValue) => | ||
store.subscribe(() => { | ||
setValue(store.getState()) | ||
}) | ||
const derivedAtom = atom( | ||
(get) => get(baseAtom), | ||
(_get, _set, action: A) => { | ||
store.dispatch(action) | ||
} | ||
) | ||
return derivedAtom | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import React from 'react' | ||
import { fireEvent, render, act } from '@testing-library/react' | ||
import { createStore } from 'redux' | ||
import { Provider, useAtom } from '../../src/index' | ||
import { atomWithStore } from '../../src/redux' | ||
|
||
it('count state', async () => { | ||
const initialState = { count: 0 } | ||
const reducer = (state = initialState, action: { type: 'INC' }) => { | ||
if (action.type === 'INC') { | ||
return { ...state, count: state.count + 1 } | ||
} | ||
return state | ||
} | ||
const store = createStore(reducer) | ||
const storeAtom = atomWithStore(store) | ||
const Counter: React.FC = () => { | ||
const [state, dispatch] = useAtom(storeAtom) | ||
|
||
return ( | ||
<> | ||
count: {state.count} | ||
<button onClick={() => dispatch({ type: 'INC' })}>button</button> | ||
</> | ||
) | ||
} | ||
|
||
const { findByText, getByText } = render( | ||
<Provider> | ||
<Counter /> | ||
</Provider> | ||
) | ||
|
||
await findByText('count: 0') | ||
|
||
fireEvent.click(getByText('button')) | ||
await findByText('count: 1') | ||
expect(store.getState().count).toBe(1) | ||
|
||
act(() => { | ||
store.dispatch({ type: 'INC' }) | ||
}) | ||
await findByText('count: 2') | ||
expect(store.getState().count).toBe(2) | ||
}) |
Oops, something went wrong.