Context
Context API
The Context API comes in handy when we want to move state or make it easy accessible to distant children.
A context can not only contain state but also actions that help us to mutate that state. We can easily
combine the Context API with useReducer
to dispatch actions that we pull in from a certain context in screens.
Automate Context Creation
To automate the creation of a context and action it provides you can use the following boilerplate code (createDataContext.tsx
):
import React, {createContext, useReducer} from 'react';
export interface Action {
type: string,
payload: any
}
export default (reducer: any, actions: any, initialState: any) => {
const Context = createContext({} as any);
const Provider = ({children}: { children: any }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const boundActions = {} as any;
for (let key in actions) {
boundActions[key] = actions[key](dispatch);
}
return (
<Context.Provider value={{state, ...boundActions}}>
{children}
</Context.Provider>
);
};
return {Context, Provider};
};
Usage
In a context, e.g. AuthContext.ts
, all you need is to create the reducer, the actions and call the function from above
and export the context and provider.
const authReducer = (state: any, action: Action) => {
switch (action.type) {
case 'signin':
return {errorMessage: '', token: action.payload};
default:
return state;
}
};
const signIn = (dispatch: any) => async ({email, password}) => {
const response = await authApi.post('/signin', {email, password});
dispatch({type: 'signin', payload: response});
};
export const {Context, Provider} = createDataContext(
authReducer, // reducer
{signIn}, // actions
{} // initial state
);
Provide inApp.tsx
:
import { Provider as AuthProvider } from "./src/context/AuthContext";
const App = createAppContainer(...);
export default () => {
return (
<AuthProvider>
<App/>
</AuthProvider>
);
}
Consume in any screen:
import {Context as AuthContext} from '../context/AuthContext';
const {state, sigin} = useContext(AuthContext);