The document compares Redux and Context API for state management in React Native apps. It discusses the purpose and building blocks of each, provides an example counter app using both approaches, and compares their key differences. Redux is designed for centralized state management while Context API is for passing data through a component tree without prop drilling. Redux uses actions, reducers and a store while Context API uses contexts and providers. The example shows implementing each approach and the document concludes that Redux is better for large complex apps that need precise state management.
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
Redux vs Context API: Understanding use cases and building a demo app
1. Redux and
Context API with
React Native
App:
Introduction,
Use Cases,
Implementation,
and Comparison
www.bacancytechnology.com
2. Developer 1 and Developer 2 were fighting
over which state management tool is
better- Redux or Context API. They both
listed pros and cons but sadly none realized
the actual use case and purpose of Redux
and Context API.
If you’re one of the developer 1 or 2, then
continue reading the tutorial to learn why it
shouldn’t be Redux vs Context API.
4. If you’re having a Javascript background
then you might be familiar with the terms
Redux and Context API. And probably, you
might have come across so many blogs that
debate on which is better- Redux vs Context
API. I assumed the same unless I realized
it’s not!
After reading a bunch of blogs, I concluded
the purpose of both the tools and how
different they are from each other. If you
aren’t aware yet, don’t worry this tutorial
will help you understand the use cases of
both tools with a basic demo example. Here,
we will build an app using both approaches
and discuss them.
Let’s get started, then!
6. Understanding Redux and Context API
Comparing the working of Redux and
Context API
Exploring the purpose and use case of
Redux and Context API
A demo application using Redux and
Context API approach
8. According to documentation-
Redux is a pattern and library for managing
and updating application state, using events
called “actions”. It serves as a centralized
store for state that needs to be used across
your entire application, with rules ensuring
that the state can only be updated in a
predictable fashion.
The documentation clearly mentions that
redux is for “managing state” and
understanding how the state is updated.
9. The primary goal of redux, as
mentioned in the doc, is to manage and
keep track of the state.
Keeping your state management logic
separate from the user interface layer
Faster logic debugging
Redux is mainly used to manage the state of
React applications in a centralized place
where to access the state anywhere in the
application. Technically, The concept of
Redux is based on Flux architecture and this
concept isn’t restricted to React apps; there
are implementations in different
technologies, as well (e.g. NgRx for Angular).
But Redux is particularly implemented with
React.
Use Cases of Redux
10. redux: For the functions like
createStore(), combineReducer() etc.
react-redux: For the functions like
connect() etc.
Packages needed
Building Blocks of Redux
It consists of mainly four building blocks:
1. Reducer: These are functions with state
and actions passed in as arguments. It
contains “action.type” in switch cases which
returns the changed value. It optionally
accepts the payload (generally created in a
separate file known as reducers.js)
2. Store: Store is the collection of all data.
You can pass it to the provider.
11. 3. Provider: A React component that accepts
store as an argument (usually created in
index.js)
4. Actions: Functions that provide/return
action type and payload to the dispatcher
which will further call the respective
reducer (generally created in a separate file
known as actions.js)
13. React documentation explains context API
as-
Context provides a way to pass data
through the component tree without having
to pass props down manually at every level.
In a typical React application, data is passed
top-down (parent to child) via props, but
such usage can be cumbersome for certain
types of props (e.g. locale preference, UI
theme) that are required by many
components within an application. Context
provides a way to share values like these
between components without having to
explicitly pass a prop through every level of
the tree.
If you can observe the documentation
states context for “passing” and “sharing”
values and mention nothing about
“managing the state”
14. The main purpose of using context API is
avoiding ‘prop drilling’ – passing prop at every
level. It is more like a pipeline used to pass
values from one end to another.
Context API provides the easiest way for
passing data through the component tree so
that you don’t have to pass props down
manually at every level. For example, assume
we have a component tree consisting of A, B, C,
and D components. Now you need to pass props
from A to D, so rather than passing it A > B > C >
D,i.e., to every component, with the help of
context you can directly pass to A > D.
Now, many blogs have mentioned that Context
API is the best replacement for Redux because
it’s in-built and you don’t have to install
dependencies for the same. Is this really true-
Can Context API replace Redux? We will discuss
this in a further section. Stay tuned to explore!
Use Cases of Context API
15. We can divide the Context API into three
blocks:
1. Context: Use createContext() function
that takes the default value as a first
argument. Here it is optional to pass a
Javascript object. You can implement
multiple contexts in your app.
2. Provider: After creating context, the
Provider provides the capability for
accessing the context. It provides
functions & data to pass values further to
the component.
3. Consumer: Consumer allows access to
the value to child components which are
wrapped by Provider. It has two types-
Building Blocks of Context
API
16. Context.Consumer: Context.Consumer
can be used for both functional and
class-based components. However,
through this approach, the context is
accessible within the render method
only.
Static ContextType: Static
contextType can be used only for
Class-based components.
18. The example below is based on a
Counter. The initial value will be 0 and
it has two buttons to increment and
decrement the value.
Inside the main parent counter
component, there will be three child
components-
one for changing the counter value
two for each of the buttons.
The initial setup would be the same for both
Context and Redux approaches.
Create a React Native App
Initially, create a react native app using the
following command
react-native init CounterDemo
20. Install Required dependencies for Redux
npm install redux --save
npm install react-redux --save
Redux Store Set Up
We will create our store within our App.js
file.
21. // App.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import totalReducers from
'./reducers/index.js';
import Counter from
'./components/counters';
const store = createStore(totalReducers);
export default class App extends
Component{
render(){
return(
);
}
}
22. Here we are importing totalReducers
from the reducers folder.
createStore() function accepts one
argument as totalReducers object and
generates the store.
The Provider component makes sure
the store is available throughout the
application.
Reducers Set Up
Reducers return the data required by the
application. In this demo, the reducer will
return the updated counter value. Here is
our counterReducer.js file inside the
reducers folder.
24. The reducer defined above will always
return the count value.
Increment & Decrement are the actions
types that will update the value as shown
above.
We will combine all the reducers inside
the index.js file inside the reducers
folder.
Explanation
// reducers/index.js
import {combineReducers} from 'redux';
import counterReducer from
'./counterReducer';
const totalReducers= combineReducers({
count: counterReducer,
});
export default totalReducers;
25. Create two actions: Increment & Decrement.
// actions/index.js
export function increment(){
return{
type: "Increment"
};
}
export function decrement(){
return{
type: "Decrement"
};
}
Here we will combine all the reducers as
arguments of the combineReducers()
function of the Redux library.
Explanation
Actions Set Up
26. mapStateToProps() – It simply accepts
your reducer data, and converts it into a
simple usable prop. With the help of
this.props.data we will use data as a
prop in our component.
We will simply create only one component
called a counter component. For using
reducers and actions, we have to implement
these functions:
function mapStateToProps(state){
return{
count: state.count
};
}
UI Component
27. mapDispatchToProps() – It accepts your
actions, and converts them into a simple
usable prop.
Note: Keep in mind how we assigned names
to reducers in the combineReducers
function because we have to use the same
name for calling respective reducers.
function mapDispatchToProps(dispatch){
return bindActionCreators({increment,
decrement}, dispatch)
}
28. Note: bindActionCreators function simply
combines our actions into one object.
Moving towards the component that
manages the user interface.
// component/counter.js
class Counters extends Component {
constructor(props) {
super(props);
}
render() {
return (
{'The Redux Approach'}
{this.props.count}
this.props.increment()}>
Increment + this.props.decrement()}>
Decrement -
29. );
}
}
function mapStateToProps(state) {
return {
count: state.count,
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({increment,
decrement}, dispatch);
}
export default connect(mapStateToProps,
mapDispatchToProps)(Counters);
For styling your component you can use the
below code
31. Finishing up
So far we are done with redux set up, logic,
and user interface for the counter demo.
Now, just a simple step remaining – import
our App file in our index.js file.
// index.js
import {AppRegistry} from 'react-native';
import App from './src/App.js';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName,
() => App);
Git Repo link: https://github.com/sunil-
bacancy/CounterDemo
33. Since the context API is in-built
functionality we don’t need to install third-
party dependencies.
Folder structure
Create a folder src at the root of your app.
Within the src folder, we have to create 3
folders that are reducers, components, state
and one file App.js.
34. Just like Redux, declare reducer with
Context API.
// reducers/globalReducer.js
export default countReducer = (state , action) => {
switch (action.type) {
case "Increment":
return{
...state,
counter: state.counter + 1,
}
case "Decrement":
return{
...state,
counter: state.counter - 1,
}
default:
return{
state
}
}
}
Reducer Set Up
35. Create the context
Create a context using createContext()
and pass the initial state as arguments.
You can also define without passing
arguments.
Define a function that will pass the data
via Provider.
useReducer() will take a reducer having
default state, then return the updated
value and dispatch the function.
Inside the Provider function, use
useReducer() with arguments- reducer
and initial state. The returned and
dispatched states are later passed as
values to the Provider.
// state/globalState.js
37. Providing Context
After creating the context, we need to
provide the context so that it is accessible in
the child components. For that, you need to
wrap it within the Provider.
// src/App.js
import React, { Component } from 'react';
import GlobalProvider from
'./state/globalState';
import Counters from
'./components/counter';
export default class App extends Component
{
render(){
return (
)
}
}
38. Consuming Context
Use useContext() for consuming the context
in respective child components.
// components/counter.js
import React, { Component, useContext }
from 'react';
import { View, Text, TouchableOpacity,
StyleSheet } from 'react-native';
import {GlobalContext} from
'../state/globalState';
const Counters = () => {
const {state} = useContext(GlobalContext);
const {dispatch} =
useContext(GlobalContext);
return(
39. {'The Context API Approach' }
{ state.counter }
dispatch({type: "Increment"})}
>
Increment +
dispatch({type: "Decrement"})}
>
Decrement -
)
}
export default Counters;
For styling your component you can use the
below code.
43. Redux
Storing and managing values
Works outside React components
Avoids prop-drilling
Through dispatching an action one can update
the value
Provides DevTools to show history of actions
and state values
Allows application code for triggering side
effects through middlewares
Context API
Not for storing or managing values
Works in React components only
Passes a single value be it objects, primitives,
classes, etc.
Avoids prop-drilling
Provides current context value for Provider
and Consumer but doesn’t display any history
of how the value is changed.
Excludes side effects mechanism – exclusively
for component rendering
45. I hope the tutorial helped you understand
how different Context and Redux are.
Moreover, try to implement both the
approaches and play around with the code
to dig deeper. For more such React Native
tutorials, we have a React Native Tutorials
page that consists of step-by-step
guidelines with the github source.
I can understand how difficult it can be to
organize and manage a global store for a
complex application, and also how precise
you need to be for implementing Context
API in your application. In case you have a
large and complex project and want to
implement Redux or Context API then feel
free to contact us and hire React Native
developer.