简体   繁体   English

在nextjs中页面之间路由时如何保留上下文API state?

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

I have a project with nextJs and typescript.我有一个带有 nextJs 和 typescript 的项目。 I used context API for handling global states in my application.我使用上下文 API 来处理我的应用程序中的全局状态。 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.我的问题是当我在页面之间导航时,我的 state 会再次重新评估。(我使用 nextjs 链接标签)换句话说,我希望我的上下文只更新一次,而不是每次在页面之间导航时更新。 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.我在我的 header 组件中调用 setPermissionsHandler ,我的 header 组件在所有页面中。

this is my header component这是我的 header 组件

 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.就像上面评论中的 Neutrino 一样,我也遇到了这个问题。

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 .现在不同的页面有不同的数据,当我使用 router.push() 时,新的页面道具不会更新上下文,因为上下文包装器位于 _app 中,它不会被卸载,并且useReducer 的工作方式与useState类似。 When the page changes you would need to set state or use a reducer to change the context state.当页面更改时,您需要设置 state 或使用减速器来更改上下文 state。

So we have a few options here所以我们在这里有几个选择

1:Use a so as the app refreshes when changing page next/link. 1:在更改页面下一页/链接时使用一个so作为应用程序刷新。 This appears to be the best solution.这似乎是最好的解决方案。 Also router.refresh() can behave like next/link router.refresh() 也可以表现得像 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. 2:当您更改页面时,我们将当前上下文 state(字符串化)与传入状态/道具进行比较,如果设置不同则设置上下文。 We also also have some hybrid current state vs incoming props and set context where appropriate.我们也有一些混合电流 state 与传入道具并在适当时设置上下文。 Very messy and bad way i feel.我感觉非常混乱和糟糕。

3:Instead of putting the context wrapper inside the _app, instead put inside each page component. 3:而不是将上下文包装器放在_app中,而是放在每个页面组件中。 So when we use router.push() and new context is unmounted/mounted所以当我们使用 router.push() 并且新的上下文被卸载/安装时

Daniel丹尼尔

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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