在React和Next中将cookie重写到本地存储

问题描述 投票:0回答:1

一个项目由 4 个来源组成。在这个项目中,我想将cookie重写到本地存储。我已经在用户源中实现了它,并且它正确保存在本地存储中。然而,在登陆源中,尽管进行了更改,我仍无法在本地存储中检索令牌。重要的一点是,当我登录用户时,它应该也会自动登录到登陆。下面,我附上了登陆源的文件。

main.js

import { useContext, createContext, useState, useEffect } from 'react'
// import { setCookie } from 'cookies-next'
import { useRouter } from 'next/router'
import { cookies } from 'next/headers'
import { useLogout } from '@/core/services/react-query/auth'

const context = createContext()

export const useMainContext = () => {
    return useContext(context)
}

const MainContextProvider = ({
    children,
    theme: initialTheme,
    token: _token,
  
}) => {
    const [theme, _setTheme] = useState(initialTheme)
    const [token, _setToken] = useState(_token)
    
    const [isOpen, _setIsOpen] = useState(false)

    const router = useRouter()
    const { pathname, asPath, query, locale } = router

    useEffect(() => {  
        const storedTokenFromCookies = document.cookie  
            .split('; ')  
            .find(row => row.startsWith('token='));  
        
        if (storedTokenFromCookies) {  
            const tokenValue = storedTokenFromCookies.split('=')[1];  
            setToken(tokenValue);  // Set token in the state  
            localStorage.setItem('token', tokenValue);  // Also set it in localStorage  
            console.log('User found in cookies:', tokenValue);  

            // Redirect user to profile page  
            router.push('/profile');  
        } else {  
            const storedToken = localStorage.getItem('token');  
            if (storedToken) {  
                setToken(storedToken);  // Update state if the token exists in localStorage  
            }  
        }  
    }, [router]);  

    const toggleTheme = () => {
        const value = theme === 'dark' ? 'light' : 'dark'
        // setCookie('theme', value)
        localStorage.setItem('theme', value)
        _setTheme(value)

        if (value === 'dark') 
        {document.documentElement.classList.add('dark')
        }else {document.documentElement.classList.remove('dark')}
    }

    const toggleLang = () => {
        const lang = locale === 'en' ? 'fa' : 'en'
        router.push({ pathname, query }, asPath, { locale: lang })
        document.documentElement.setAttribute(
            'dir',
            lang === 'en' ? 'ltr' : 'rtl'
        )
        // setCookie('lang', lang, { path: '/' })
        localStorage.setItem('lang', lang)
    }

    const setToken = (value) => {
        // setCookie('token', value)
        localStorage.setItem('token', value)
        _setToken(value)
    }

    const setIsOpen = () => {
        _setIsOpen((prevState) => !prevState)
    }
   
    return (
        <context.Provider
            value={{
                theme,
                toggleTheme,
                toggleLang,
                token,
                setToken,
                setIsOpen,
                isOpen,
            }}>
            {children}
        </context.Provider>
    )
}

export default MainContextProvider

_document.js

import Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components';

class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet()
        const originalRenderPage = ctx.renderPage
    
        try {
            // Run the React rendering logic synchronously
            ctx.renderPage = () =>
                originalRenderPage({
                    // Useful for wrapping the whole react tree
                    enhanceApp: (App) => (props) =>
                        sheet.collectStyles(<App {...props} />),
                    // Useful for wrapping in a per-page basis
                    enhanceComponent: (Component) => Component,
                })

            // Run the parent `getInitialProps`, it now includes the custom `renderPage`
            const initialProps = await Document.getInitialProps(ctx)
            const theme = ctx.req?.cookies?.theme || 'dark'
            const lang = ctx.req?.cookies?.lang
            const dir = lang === 'en' ? 'ltr' : 'rtl'
            
            return {
                ...initialProps,
                theme,
                dir,
                styles: [initialProps.styles, sheet.getStyleElement()]
            }
        }
        finally {
            sheet.seal()
        } }
    render() {
        return (
            <Html className={this.props.theme} dir={this.props.dir}>
                <Head />
                <body>
                <Main />
                <NextScript />
                </body>
            </Html>
        )}}

export default MyDocument

_app.js

import '@/styles/globals.css'
import Providers from '@/components/layout/Providers'
import { getCookie, setCookie } from 'cookies-next'
import MainLayout from '@/components/layout/main/MainLayout'
import { GlobalStyles } from '@/styles/styled/GlobalStyle.styled'

export default function App({ Component, pageProps, theme, ...rest }) {
    // TODO: if cookie is empty
    let _theme = theme
    if (!_theme) {
        _theme = 'dark'
        setCookie('theme', _theme)
    }

    return (
        <Providers theme={_theme} {...rest}>
            <MainLayout pageProps={pageProps}>
                <GlobalStyles />
                <Component {...pageProps} />
            </MainLayout>
        </Providers>
    )
}

App.getInitialProps = ({ ctx }) => {
    const theme = getCookie('theme', ctx)
    const token = getCookie('token', ctx)

    return {
        theme,
        token,
    }
}

考虑到登录应该在登陆页面渲染时完成,如何将cookie重写到本地存储?

reactjs next.js cookies local-storage
1个回答
0
投票

我在这里看到一个设计问题。 Session是为了让用户可以访问api。 对于任何与 UI 相关的东西,你都有状态。 不要试图通过会议,而是尝试从以下方面思考:

  • 如何在每个 api 调用上发送会话(也许是 cookie,因为您不再需要担心在每个 api 调用上附加会话)
  • 如果 api 调用因 401 失败该怎么办(在应用程序中有一个状态,
    isLoggedIn
    ,如果为 false,则重定向用户登录)
© www.soinside.com 2019 - 2024. All rights reserved.