Setting up Redux
In this recipe, you will be guided through the process of setting up a disk persistence-enabled Redux store in your React Native app.
βΉοΈ It is assumed you have an understanding of Redux concepts, how it works, and knowledge of the most common tools revolving Redux's ecosystem. In case you don't, first please go through the official introductory document before proceeding. We also recommend you read the Advanced Tutorial material, otherwise, it might be difficult for you to follow this recipe.
1. Install dependencies
Install the following packages:
redux
react-redux
redux-devtools-extension
redux-thunk
redux-persist
@react-native-community/async-storage
2. Configuring your store
This section demonstrates how to create your Redux store. The store is wired up with the following functionality:
- Dispatch (asynchronous) action creators with
redux-thunk
middleware. - Debug, while in development, what's going on in the store with Redux DevTools by activating
redux-devtools-extension
. - Manage state persisted in disk with
redux-persist
backed by@react-native-community/async-storage
as storage engine. The state is rehydrated back automatically to the point where it was left off when the app was closed.
Create the files as shown in the sections below.
src/shared/state/buildStore.js
How to use your store and tweak it further:
- Add your own reducers to the
reducers
object. Theapp
reducer above is just a sample reducer. - Add your own middlewares to the
middleware
array. - The
modules
object allows you to pass arbitrary data to your action creators and middlewares. An API client module is a good example of whatmodules
can be used for. Feel free to rename this variable to better suit your needs.
src/shared/state/persist/index.js
src/shared/state/persist/config.js
src/shared/state/persist/migrations.js
Persistence allows you to:
- Select, through blacklists, whitelists and transforms, which parts of the state get to be serialized to disk and deserialized (rehydrated) back to the app.
- Maintain different versions of the state and move from an older version to a newer one with migrations.
By default, the whole state tree is persisted. Head to redux-persist
repository to learn more about how Redux store persistence works and how it can be configured and customized.
StoreProvider
3. Create The next step is to put together Redux's Provider
and redux-persist
's PersistGate
.
Create the files as shown in the sections below.
src/shared/modules/react-native-store/StoreProvider.js
How StoreProvider
works:
- Persistence is enabled by default. You can choose to disable persistence by setting
persist
prop tofalse
.StoreProvider
does not listen to changes topersist
after mounting. - You can choose to purge the persisted state by setting
purge
prop totrue
.StoreProvider
does not listen to changes topurge
after mounting. - The
children
render prop is called withstoreReady
set tofalse
while the store is rehydrating. Once rehydrated,storeReady
changes totrue
.
StoreProvider
3. Wrap navigation with Finally, all that is left to do is render StoreProvider
on top of your app's navigation.
βοΈNote that if you have other components that require access to the Redux store, make sure
StoreProvider
is rendered before them.
src/app/App.js
βοΈDo not render your app's navigation before the store is rehydrated! Use
storeReady
to determine when the navigation should be rendered. You should render a splash screen while the store is being rehydrated and then hide it when it's done rehydrating.
4. State directory tree
We recommend the following structure to organize Redux's concerns: actions, action types, reducers, selectors and middlewares. In the simplistic and contrived example below, the app
directory represents a slice of the global state your app manages. As your app's state grows, this approach scales really well as it enables you to split up concerns by domains. Suppose you need state to manage user-related information: all you have to do is create a user
directory, at the same level as app
's, and replicate the file structure.
src/shared/state/app/index.js
src/shared/state/app/actionTypes.js
src/shared/state/app/actions.js
src/shared/state/app/reducer.js
src/shared/state/app/selectors.js
src/shared/state/app/middlewares.js
5. Complete store configuration
Following through the example above, the store setup needs to be concluded by adding app
's reducer and middleware(s):
src/shared/state/buildStore.js
6. Source code
If'd like, feel free to checkout the branch from the boilerplate's repository to see the persistence-enabled Redux store working on both Android and iOS. You can also find tests for StoreProvider
.
Full diff: https://github.com/moxystudio/react-native-with-moxy/compare/master...feat/add-store-provider