Version: 7.11.0

React Context API

React Context API

React Context API provides a easy way to pass data through the component tree without having to pass props down manually at every level. You can find more about the Context API in React documentation.

You can use the React Context API with React Native Navigation with a limitation. In this example, we are going to create a screen which uses the Counter Context.

Limitation

As RNN screens are not part of the same component tree, updating the values in the shared context does not trigger a re-render across all screens. However you can still use the React.Context per RNN screen component tree.

If you need to trigger a re-render across all screens, there are many popular third party libraries such as MobX or Redux.

Create a Counter context

// CounterContext.tsx
import React from 'react';
// Declaring the state object globally.
const initialCounterState = {
count: 0,
};
const counterContextWrapper = (component?: React.Component) => ({
...initialCounterState,
increment: () => {
initialCounterState.count += 1;
component?.setState({ context: counterContextWrapper(component) });
},
decrement: () => {
initialCounterState.count -= 1;
component?.setState({ context: counterContextWrapper(component) });
},
});
type Context = ReturnType<typeof counterContextWrapper>;
export const CounterContext = React.createContext<Context>(counterContextWrapper());
interface State {
context: Context;
}
export class CounterContextProvider extends React.Component {
state: State = {
context: counterContextWrapper(this),
};
render() {
return (
<CounterContext.Provider value={this.state.context}>
{this.props.children}
</CounterContext.Provider>
);
}
}

Register the screen

When registering the screen that will be using the Counter Context, we need to wrap it with the Counter Context Provider we created earlier.

// index.tsx
import { Navigation } from 'react-native-navigation';
import { CounterContextProvider } from './CounterContext';
import { App } from './App';
Navigation.registerComponent(
'App',
() => (props) => (
<CounterContextProvider>
<App {...props} />
</CounterContextProvider>
),
() => App
);

Consuming the context

You can consume the Counter Context any way you want such as Provider.Consumer or React.useContext like in the example below.

// App.tsx
import React from 'react';
import { Button, Text, View } from 'react-native';
import { CounterContext } from './CounterContext';
export const App = () => {
// Using useContext API
const { count, increment, decrement } = React.useContext(CounterContext);
return (
<View>
<Text>{`Clicked ${count} times!`}</Text>
<Button title="Increment" onPress={increment} />
<Button title="Decrement" onPress={decrement} />
</View>
);
};
// App.tsx
import React from 'react';
import { Button, Text, View } from 'react-native';
import { CounterContext } from './CounterContext';
export const App = () => {
// Using Context consumer
return (
<CounterContext.Consumer>
{({ count, increment, decrement }) => (
<View>
<Text>{`Clicked ${count} times!`}</Text>
<Button title="Increment" onPress={increment} />
<Button title="Decrement" onPress={decrement} />
</View>
)}
</CounterContext.Consumer>
);
};