Skip to main content

Context

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.

AppContext

This context will provide all global states related to the user app setting and preferences.

First It check if any cookies are set.

context/AppContext.tsx - Get preference cookies if exist
const menuInitialState = cookie.get("isSettingMenuCollapsed")
? stringToBoolean(cookie.get("isSettingMenuCollapsed"))
: true;
const themeInitialState = cookie.get("theme") ? cookie.get("theme") : "light";

On app start we will set our global state with some default props or with set's cookies

AppContext.tsx - Initial state
const initialState = {
theme: themeInitialState,
isSettingMenuCollapsed: menuInitialState,
isSessionMenuCollapsed: menuInitialState,
globalLocale: "fr",
finish: false,
};

Available actions

Their is 5 actions that can be dispatch:

  • SWITCH_THEME that change the default user theme preference
  • SWITCH_LOCALE that change the default user local setting
  • SWITCH_MENU_SESSION that change the state of the menu for this session
  • SWITCH_MENU_SETTING that change the default user menu preference
  • SAVE_SETTINGS that save all settings and preference for a user in cookies
AppContext.tsx - Actions
function reducer(state: State, action: Action) {
switch (action.type) {
case "SWITCH_THEME":
return {
...state,
theme: action.theme,
};
case "SWITCH_LOCALE":
return {
...state,
globalLocale: action.globalLocale,
};
case "SWITCH_MENU_SESSION":
return {
...state,
isSessionMenuCollapsed: action.isSessionMenuCollapsed,
};
case "SWITCH_MENU_SETTING":
return {
...state,
isSettingMenuCollapsed: action.isSettingMenuCollapsed,
isSessionMenuCollapsed: action.isSettingMenuCollapsed,
};
case "SAVE_SETTINGS":
saveUserSettings(
state.isSettingMenuCollapsed,
state.theme!,
state.globalLocale
);
default:
return state;
}
}

How to use ?

Dispatch event
import { useAppDispatch } from "context/AppContext";
const dispatchMenu = useAppDispatch();

const switchMenuSetting = useCallback(
() =>
dispatchMenu({
type: "SWITCH_MENU_SETTING",
isSettingMenuCollapsed: !isSettingMenuCollapsed,
}),
[dispatchMenu, isSettingMenuCollapsed]
);

For accessing a specific state just use this snippet.

Access Global State
import { useAppState } from "context/AppContext";
const { isSettingMenuCollapsed } = useAppState();

AuthContext

This context is responsible for Auth related state.

Queries or mutations need to be requested by an authenticated user. Every request needs a proper header after login success.

AuthContext.tsx - Login
const { mutate } = useLoginMutation<Error>(graphqlRequestClient, {
onSuccess: (
data: LoginMutation,
_variables: LoginMutationVariables,
_context: unknown
) => {
if (data?.login?.accessToken) {
cookie.set("token", data.login.accessToken);
// Set Bearer JWT token to the header for future request
setHeader(data.login.accessToken);
const user = decodeJWT(data.login.accessToken);
setUser(user);
router.push("/");
showSuccess(t("messages:login-success"));
}
},
onError: (error) => {
showError("messages:error-login");
},
});

const login = async ({
username,
password,
warehouseId,
}: LoginMutationVariables) => {
mutate({ username, password, warehouseId });
};

The login function is called on login form submits. If it's success it will set a JWT in cookies and set the right header for a specify request. Then it will redirect the user to the app.

AuthContext.tsx - Set Header
const setHeader = (token: string) => {
if (IS_FAKE) {
if (IS_SAME_SEED) {
requestHeader = {
"X-API-fake": "fake",
"X-API-seed": "same",
authorization: `Bearer ${token}`,
};
} else {
requestHeader = {
"X-API-fake": "fake",
authorization: `Bearer ${token}`,
};
}
} else {
requestHeader = {
authorization: `Bearer ${token}`,
};
}

const graphqlClientWithHeader = new GraphQLClient(
process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT as string,
{
headers: requestHeader,
}
);
setGraphqlRequestClient(graphqlClientWithHeader);
};

To access all states and functions just call the useAuth hook.

AuthContext.tsx - Set Header
import { useAuth } from "context/AuthContext";

const { graphqlRequestClient, login } = useAuth();

DrawerContext

Learn more about DrawerContext