REACT HOOKS AND CONTEXT API WITH REACT NATIVE
React Native brings the power of React to mobile app development. React Native allows you to write UI components in JavaScript that compiles native code for iOS and Android.?
The component-based approach (CBA) of React Native empowers the developer to create a maintainable application by separating different parts of logic and state into dedicated components.
Why do we need the state at all?
For an application, the state is the interface between your data from the backend or local change and the representation of this data with elements in the frontend. The state can keep the data of different components in sync because each state update will re-render all relevant components. The state can be a medium to communicate between different components as well.
Because the state plays an essential role in applications and there are so many different third-party libraries to keep your state managed globally.
In this article, I will demonstrate React's Hooks and Context API are making simple and efficient global state management for React Native applications. In older versions, it was only possible with a third-party state management library such as Redux, Unstated, etc.
If you have some hands-on experience in React Native and if you know the basic use-case of setState, this is the right article for you. If you are new to React Native, you may find everything about React state management from this official documentation.?
Let's see what is Hooks and the basic use-case of the simplest Hook: useState
HOOKS
Hooks are a new addition in React 16.8 that enables you to use state and many other React features without writing a class. As provided by the Official Documentation from the Facebook React team, the motivation for Hooks is that Hooks solve these problems.
The Basic usage of Hooks
As you can see below, I’ve created Counter.js to be a functional component containing a simple number counter with a button to increase the count with each button press.?
/Counter.js
import React, { useState } from 'React';
import { Text, Button, View } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>{count}</Text>
? ? ? <Button?
? ? ? ? onPress ={value => setCount(count + 1)}
? ? ? ? title="Increase" />
</View>
);
};
export default Counter;
One Hook is being used here: useState?
useState is responsible for keeping the local state of the Counter component. You can call useState as many times as needed, and each call is responsible for storing exactly one state key. We use array destructuring to get the two returned values from useState: the name of the state key (count) and the function responsible for modifying it (setCount).
You can find great stuff about Hooks from the official documentation provided by the Facebook React team.
Then, we are moving to the next React feature: Context API
CONTEXT API
Context API was a part of React for a long time. Context is designed to share data that can be considered “global” for a tree of React components.
The basic usage of Context API
The usage of Context is pretty straightforward.?
createContext creates a Context for the application:
/MyContext.js
import { createContext } from 'react';
const MyContext = createContext();
export default MyContext;
Provider provides the value to all child components of App:
/App.js
import React, { Component } from 'react';
import MyContext from './MyContext';
import MyComponent from './MyComponent';
export default class App extends Component {
render() {
return (
<MyContext.Provider value={{ sentence: 'Welcome to React!' }}>
<MyComponent />
</MyContext.Provider>
);
}
}
And Consumer allows to access the value in your MyComponent:
领英推荐
/MyComponent.js
import React from 'react';
import { Text, View } from 'react-native';
import MyContext from './MyContext';
const MyComponent = () => (
<MyContext.Consumer>
{value => (
<View>
<Text>{value.sentence}</Text>
</View>
)}
</MyContext.Consumer>
);
export default MyComponent;
For more implementation details, please check the official documentation, if you are interested.
WHAT HAPPENS IF YOU COMBINE HOOKS AND CONTEXT API?
This is an example of a React Native CLI application that uses Hooks and Context API together for global state management. It contains a simple counter and a simple input field.
The following image of the high-level view of the application will make it easy for you to understand what we are doing here.
The file structure of the application is as follows.
FILE STRUCTURE
android
ios
node_modules
src
|__Components
| |__Counter.js
| |__User.js
|__Store
|__Contex.js
|__CounterState.js
|__UserState.js
index.js
StateProvider.js
App.js
app.json
Package.json
First of all, we are going to make Context inside the Context.js file.
/src/Store/Context.js
import { createContext } from 'react';
const Context = createContext({});
export default Context;
Then we can create state files that provide states and actions for Counter and User.
/src/Store/CounterState.js
import { useState } from 'react';
const CounterState = () => {
? const [counter, setCounter] = useState({ value: 356 });
? increaseCounter = () => {
? ? setCounter({ ...state, value: state.value + 1 });
? };
? decreaseCounter = () => {
? ? setCounter({ ...state, value: state.value - 1 });
? };
? return {
? ? counter,
? ? increaseCounter,
? ? decreaseCounter,
? };
}
export default CounterState;
.
/src/Store/UserState.js
import { useState } from 'react';
const UserState = () => {
? const [user, setUser] = useState({ name: 'Watson' });
? setUserName = name => {
? ? setUser({ ...user, name });
? };
? return {
? ? user,
? ? setUserName,
? };
};
export default UserState;
Now we have to wrap our App component with Context Provider. For that, I’m creating a file called StateProvider.js in the root folder of the application.
/StateProvider.js
import React from 'react';
import App from './App';
import CounterState from './src/Store/CounterState';
import UserState from './src/Store/UserState';
import Context from './src/Store/Context';
const StateProvider = () => {
? const store = { ...CounterState(), ...UserState() };
? return (
? ? <Context.Provider value={store}>
? ? ? <App />
? ? </Context.Provider>
? );
};
export default StateProvider;
Then, we are going to create Counter.js which contains a simple counter with two buttons to increase and decrease the current count displaying in the counter.
/src/Components/Counter.js
import React, { useContext } from 'react';
import { Text, Button, View } from 'react-native';
import Context from '../Store/Context';
const Counter = () => {
? const {?
? ? counter,?
? ? increaseCounter,?
? ? decreaseCounter?
? } = useContext(Context);
? return (
? ? <View>
? ? ? <Text style={{ fontSize: 35 }}>Counter:{counter.value}</Text>
? ? ? <Button onPress ={() => increaseCounter()} title={'Increase'} />
? ? ? <Button
? ? ? ? onPress ={() => decreaseCounter()}
? ? ? ? title={'Decrease'}
? ? ? ? color={'black'}
? ? ? />
? ? </View>
? );
};
export default Counter;
User.js contains only a text and an input field.
/src/Components/User.js
import React, { useContext } from 'react';
import { Text, TextInput, View } from 'react-native';
import Context from '../Store/Context';
const User = () => {
? const { user, setUserName } = useContext(Context);
? return (
? ? <View>
? ? ? <Text style={{ fontSize: 35, marginTop: 20 }}>
? ? ? ? User:{user.name}
? ? ? </Text>
? ? ? <TextInput
? ? ? ? style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
? ? ? ? onChangeText ={text => setUserName(text)}
? ? ? ? value={user.name}
? ? ? />
? ? </View>
? );
};
export default User;
Let’s explain what is going on here.
And that’s it!
You don’t need to use any third-party state management library anymore. Everything you need is inside React, and we can use them inside our React Native, too.
Cool, right?
I hope you enjoyed reading this article. The application we have created in the above-written examples is available on this GitHub repository.