简体   繁体   中英

How to keep Context API state when routing between pages in nextjs?

I have a project with nextJs and typescript. I used context API for handling global states in my application. My problem is when I navigate between pages my state revaluates again.(i used nextjs Link tag) in other words, I want my context updated only once and not each time I navigate between pages. this is my context

 import React, {createContext, useState} from "react"; export type ResourcesType = 'ALL' | 'ORDERS' | 'ORDERS_CANCELLATION' | 'ORDERS_PARTIAL_PAID'; export type AccessType = 'ACT' | 'READ' | 'UPDATE' | 'CREATE' | 'DELETE' | 'All'; export type AccessLevel = 'DO' | 'REQUEST' | 'APPROVE'; export type PermissionType = { [key1 in ResourcesType]: { [key2 in AccessType]: AccessLevel } } | null; const PermissionsContext = createContext<{ permissions: PermissionType, setPermissionsHandler: (permissions: PermissionType) => void }>({ permissions: null, setPermissionsHandler: (permissions: PermissionType) => {} }); export function PermissionsProvider(props: any) { const [permissions, setPermissions] = useState<PermissionType>(null); const setPermissionsHandler = (permissions: PermissionType) => { setPermissions(permissions); } const context = { permissions, setPermissionsHandler } return <PermissionsContext.Provider value={context}> {props.children} </PermissionsContext.Provider> } export default PermissionsContext;

and I call setPermissionsHandler in my header component and my header component is in all pages.

this is my header component

 const Header = () => { const permissionsCtx = useContext(PermissionsContext); const initialCtx = useContext(InitialContext); useEffect(() => { console.log(permissionsCtx.permissions,'INN'); if (.permissionsCtx.permissions) { console;log('OH') const initialInstance = new HandleInitialize(). initialInstance.getInitialData().then(res => { permissionsCtx.setPermissionsHandler(res.data.result;permissions). }).catch(e => console;log(e)), } }; []); return ( <div> Hi </div> ); };

 import type {AppProps} from "next/app"; import useRouterStatus from "../hooks/useRouterStatus"; import PrimeReact from "primereact/api"; import "nprogress/nprogress.css"; /*import "primereact/resources/themes/lara-light-indigo/theme.css";*/ import "../styles/override-theme.css"; import "primereact/resources/primereact.min.css"; import "primeicons/primeicons.css"; import "tailwindcss/tailwind.css"; import "../styles/typography.css"; import "../styles/globals.css"; import "../styles/primefaces-overrides.css"; import {PermissionsProvider} from "../store/persmissions"; import {InitialProvider} from "../store/initial"; import {useEffect} from "react"; import {HandleInitialize} from "../adapter/HandleInitialize"; function MyApp({Component, pageProps}: AppProps) { return <PermissionsProvider> <Component {...pageProps} /> </PermissionsProvider>; } export default MyApp;

Seems to be a black spot.

Like Neutrino above in the comments I am hitting this issue too.

It didn't bother me for ages as on each page I got all app data so didn't notice.

Now different pages have different data and when I use router.push() the new page props don't update the context because the context wrapper is in _app which does not get unmounted and useReducer works like useState . When the page changes you would need to set state or use a reducer to change the context state.

So we have a few options here

1:Use a so as the app refreshes when changing page next/link. This appears to be the best solution. Also router.refresh() can behave like next/link

2:When you change a page we compare the current context state (stringify) with the incoming state/props and if different set context. We also also have some hybrid current state vs incoming props and set context where appropriate. Very messy and bad way i feel.

3:Instead of putting the context wrapper inside the _app, instead put inside each page component. So when we use router.push() and new context is unmounted/mounted

Daniel

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM