With React Hook widely used, component state handling and side effects are too common in function components. React Redux introduced Hook API functions as an alternative to connect()
.
In this tutorial, we will build a simple React Native app for users to write notes and save them. If you are familiar with the basic React Hook function and how to use it, you can continue with this tutorial, otherwise you should learn about the basics of React Hook first.
Install Redux
Please install Redux through the instructions here: https://redux.js.org/introduction/installation/ Then check the dependencies
in the package.json
file again.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token string">"dependencies"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token string">"@react-native-community/masked-view"</span> <span class="token punctuation">:</span> <span class="token string">"0.1.5"</span> <span class="token punctuation">,</span> <span class="token string">"expo"</span> <span class="token punctuation">:</span> <span class="token string">"~36.0.0"</span> <span class="token punctuation">,</span> <span class="token string">"react"</span> <span class="token punctuation">:</span> <span class="token string">"~16.9.0"</span> <span class="token punctuation">,</span> <span class="token string">"react-dom"</span> <span class="token punctuation">:</span> <span class="token string">"~16.9.0"</span> <span class="token punctuation">,</span> <span class="token string">"react-native"</span> <span class="token punctuation">:</span> <span class="token string">"https://github.com/expo/react-native/archive/sdk-36.0.0.tar.gz"</span> <span class="token punctuation">,</span> <span class="token string">"react-native-gesture-handler"</span> <span class="token punctuation">:</span> <span class="token string">"~1.5.0"</span> <span class="token punctuation">,</span> <span class="token string">"react-native-paper"</span> <span class="token punctuation">:</span> <span class="token string">"3.4.0"</span> <span class="token punctuation">,</span> <span class="token string">"react-native-reanimated"</span> <span class="token punctuation">:</span> <span class="token string">"~1.4.0"</span> <span class="token punctuation">,</span> <span class="token string">"react-native-safe-area-context"</span> <span class="token punctuation">:</span> <span class="token string">"0.6.0"</span> <span class="token punctuation">,</span> <span class="token string">"react-native-screens"</span> <span class="token punctuation">:</span> <span class="token string">"2.0.0-alpha.12"</span> <span class="token punctuation">,</span> <span class="token string">"react-navigation"</span> <span class="token punctuation">:</span> <span class="token string">"4.0.10"</span> <span class="token punctuation">,</span> <span class="token string">"react-navigation-stack"</span> <span class="token punctuation">:</span> <span class="token string">"2.0.10"</span> <span class="token punctuation">,</span> <span class="token string">"react-redux"</span> <span class="token punctuation">:</span> <span class="token string">"7.1.3"</span> <span class="token punctuation">,</span> <span class="token string">"redux"</span> <span class="token punctuation">:</span> <span class="token string">"4.0.5"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> |
Then install the following dependencies using the terminal
1 2 | yarn add redux react <span class="token operator">-</span> redux lodash <span class="token punctuation">.</span> remove |
The above installation helps you manage all Redux related files in one convenient place, it's called ducks. You can refer to the following article to learn more: https://medium.com/swlh/the-good-the-bad-of-react-redux-and-why-ducks-might-be-the- solution-1567d5bdc698
Add action type and creator
When Redux controls the state of an application, the state is expressed as a Javascript object. Please understand that this object is read-only, we cannot change it on our own. Which must use action to do.
Actions are events in redux. It could be a push of a button, a timer, or a network request.
To get started, create a redux
directory in src
. Then create a noteApp.js
file.
Since this app does note-related work, in the newly created file, start with the following 2 actions.
1 2 3 4 5 6 | <span class="token comment">// Action Types</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">ADD_NOTE</span> <span class="token operator">=</span> <span class="token string">'ADD_NOTE'</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">DELETE_NOTE</span> <span class="token operator">=</span> <span class="token string">'DELETE_NOTE'</span> |
Next are the functions that create these actions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token comment">// Action Creators</span> <span class="token keyword">let</span> noteID <span class="token operator">=</span> <span class="token number">0</span> <span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">addnote</span> <span class="token punctuation">(</span> note <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> <span class="token constant">ADD_NOTE</span> <span class="token punctuation">,</span> id <span class="token punctuation">:</span> noteID <span class="token operator">++</span> <span class="token punctuation">,</span> note <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">deletenote</span> <span class="token punctuation">(</span> id <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> <span class="token constant">DELETE_NOTE</span> <span class="token punctuation">,</span> payload <span class="token punctuation">:</span> id <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Add a Reducer
The part that receives actions is called the reducer. Whenever the action is triggered, the application state will change. Managing this state relies on reducers.
The Reducer is a pure function that calculates the next state based on its previous state. It always returns the same output if the state doesn't change. It has two parameters state
and action
and must always return state
.
The initialized state will be an empty array. Please import more remove
in lodash.remove
that you added earlier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <span class="token comment">// import the dependency</span> <span class="token keyword">import</span> remove <span class="token keyword">from</span> <span class="token string">'lodash.remove'</span> <span class="token comment">// reducer</span> <span class="token keyword">const</span> initialState <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token keyword">function</span> <span class="token function">notesReducer</span> <span class="token punctuation">(</span> state <span class="token operator">=</span> initialState <span class="token punctuation">,</span> action <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span> action <span class="token punctuation">.</span> type <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token constant">ADD_NOTE</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token punctuation">[</span> <span class="token operator">...</span> state <span class="token punctuation">,</span> <span class="token punctuation">{</span> id <span class="token punctuation">:</span> action <span class="token punctuation">.</span> id <span class="token punctuation">,</span> note <span class="token punctuation">:</span> action <span class="token punctuation">.</span> note <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token keyword">case</span> <span class="token constant">DELETE_NOTE</span> <span class="token punctuation">:</span> <span class="token keyword">const</span> deletedNewArray <span class="token operator">=</span> <span class="token function">remove</span> <span class="token punctuation">(</span> state <span class="token punctuation">,</span> obj <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> obj <span class="token punctuation">.</span> id <span class="token operator">!=</span> action <span class="token punctuation">.</span> payload <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> deletedNewArray <span class="token keyword">default</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> state <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">default</span> notesReducer |
Customize the Redux store
Store is an object that connects actions with reducers. It provides and holds state at the application level instead of in components.
With the Reducer created, create a new store.js
file inside src/redux/
. Add the createStore
function in redux
.
1 2 3 4 5 6 7 | <span class="token keyword">import</span> <span class="token punctuation">{</span> createStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux'</span> <span class="token keyword">import</span> notesReducer <span class="token keyword">from</span> <span class="token string">'./notesApp'</span> <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span> <span class="token punctuation">(</span> notesReducer <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">default</span> store |
To connect the Redux store with the React native app, do the following in the App.js
file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Provider <span class="token keyword">as</span> PaperProvider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-native-paper'</span> <span class="token keyword">import</span> AppNavigator <span class="token keyword">from</span> <span class="token string">'./src/navigation'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Provider <span class="token keyword">as</span> StoreProvider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-redux'</span> <span class="token keyword">import</span> store <span class="token keyword">from</span> <span class="token string">'./src/redux/store'</span> <span class="token comment">// modify the App component</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">App</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> StoreProvider store <span class="token operator">=</span> <span class="token punctuation">{</span> store <span class="token punctuation">}</span> <span class="token operator">></span> <span class="token operator"><</span> PaperProvider <span class="token operator">></span> <span class="token operator"><</span> AppNavigator <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> PaperProvider <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> StoreProvider <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Access to global state
To access, use Hook's useSelector
function. It should be similar to mapStateToProps
in connect()
. The difference between them is that the hook function can return more than just objects.
Open the ViewNotes.js
file. Please add the following
1 2 3 | <span class="token comment">// ...after rest of the imports</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> useSelector <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-redux'</span> |
Next, instead of saving the note into a notes
array using useState()
, replace it as follows
1 2 | <span class="token keyword">const</span> notes <span class="token operator">=</span> <span class="token function">useSelector</span> <span class="token punctuation">(</span> state <span class="token operator">=></span> state <span class="token punctuation">)</span> |
Dispatch action
The useDispatch()
function is exactly the same as the dispatch function in the Redux store. Add it as follows
1 2 | <span class="token keyword">import</span> <span class="token punctuation">{</span> useSelector <span class="token punctuation">,</span> useDispatch <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-redux'</span> |
To dispatch the action, do the following
1 2 3 4 5 | <span class="token keyword">const</span> dispatch <span class="token operator">=</span> <span class="token function">useDispatch</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Note action</span> <span class="token keyword">const</span> <span class="token function-variable function">addNote</span> <span class="token operator">=</span> note <span class="token operator">=></span> <span class="token function">dispatch</span> <span class="token punctuation">(</span> <span class="token function">addnote</span> <span class="token punctuation">(</span> note <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token function-variable function">deleteNote</span> <span class="token operator">=</span> id <span class="token operator">=></span> <span class="token function">dispatch</span> <span class="token punctuation">(</span> <span class="token function">deletenote</span> <span class="token punctuation">(</span> id <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
And add these actions to the UI to trigger
1 2 3 4 5 6 7 8 | <span class="token operator"><</span> List <span class="token punctuation">.</span> Item title <span class="token operator">=</span> <span class="token punctuation">{</span> item <span class="token punctuation">.</span> note <span class="token punctuation">.</span> noteTitle <span class="token punctuation">}</span> description <span class="token operator">=</span> <span class="token punctuation">{</span> item <span class="token punctuation">.</span> note <span class="token punctuation">.</span> noteValue <span class="token punctuation">}</span> descriptionNumberOfLines <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">1</span> <span class="token punctuation">}</span> titleStyle <span class="token operator">=</span> <span class="token punctuation">{</span> styles <span class="token punctuation">.</span> listTitle <span class="token punctuation">}</span> onPress <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">deleteNote</span> <span class="token punctuation">(</span> item <span class="token punctuation">.</span> id <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> |
End
By using useSelector
and useDispatch
, we not only eliminate a lot of code, but also provide a better access to the functional component. You should use this method with Redux will reduce a lot of time of that code. Thank you for reading.
REF: https://heartbeat.fritz.ai/using-redux-with-react-hooks-in-a-react-native-app-cc410a77f3e2