请问 react,nextjs,useContext 刷新页面后数据丢失问题如何处理呢?

2021-12-05 13:57:19 +08:00
 sciel

_app.js 里面的代码如下

function MyApp({Component, pageProps}) {
    const [user, setUser] = useLocalStorage()
    const value = useMemo(() => ({user, setUser}), [user, setUser]);
    return <SSRProvider>
        <UserContext.Provider value={value}>
            <Layout>
                <Component {...pageProps} />
                <ToastContainer position={'top-center'} theme={'dark'}/>
            </Layout>
        </UserContext.Provider>
    </SSRProvider>
}

useLocalStorage 代码如下

// Hook
import {useState} from "react";

export const useLocalStorage = (key, initialValue) => {
    // State to store our value
    // Pass initial state function to useState so logic is only executed once
    const [storedValue, setStoredValue] = useState(() => {
        try {
            // Get from local storage by key
            const item = window.localStorage.getItem(key);
            // Parse stored json or if none return initialValue
            return item ? JSON.parse(item) : initialValue;
        } catch (error) {
            // If error also return initialValue
            // console.log(error);
            return initialValue;
        }
    });
    // Return a wrapped version of useState's setter function that ...
    // ... persists the new value to localStorage.
    const setValue = (value) => {
        try {
            // Allow value to be a function so we have same API as useState
            const valueToStore = value instanceof Function ? value(storedValue) : value;
            // Save state
            setStoredValue(valueToStore);
            // Save to local storage
            window.localStorage.setItem(key, JSON.stringify(valueToStore));
        } catch (error) {
            // A more advanced implementation would handle the error case
            // console.log(error);
        }
    };
    return [storedValue, setValue];
}
export const getCookie = (name,cookie) => {
    const value = `; ${cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

Layout.js 代码如下

import Meta from "./Meta";
import {Container, Nav, Navbar, NavDropdown} from "react-bootstrap";
import {useContext} from "react";
import {UserContext} from "../utils/userContenxt";
import jsCookie from "js-cookie";
import Router from "next/router";

export const Layout = ({children}) => {
    const {user} = useContext(UserContext)
    if (user === undefined) return (<>
        <Meta/>
        <Container>{children}</Container>
    </>)
    const {menu} = user

    function handleLogout() {
        localStorage.removeItem('u')
        jsCookie.set('token', '')
        Router.push('/login')
    }

    return (<>
        <Meta/>
        <Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
            <Container>
                <Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
                <Navbar.Toggle aria-controls="responsive-navbar-nav"/>
                <Navbar.Collapse id="responsive-navbar-nav">
                    <Nav className="me-auto">
                        {menu.map(item => (<NavDropdown key={item.id} title={item.name} id="collasible-nav-dropdown">
                            {item.Children.map(item => (item.divide === 1 ? <NavDropdown.Divider/> : <NavDropdown.Item onClick={() => Router.push(item.path)}>{item.name}</NavDropdown.Item>))}
                        </NavDropdown>))}
                    </Nav>
                    <Nav>
                        <Nav.Link eventKey={2} href="#memes">
                            {user.u.uname}
                        </Nav.Link>
                        <Nav.Link onClick={() => handleLogout()}>退出</Nav.Link>
                    </Nav>
                </Navbar.Collapse>
            </Container>
        </Navbar>
        {children}
    </>)
}
1542 次点击
所在节点    程序员
8 条回复
sciel
2021-12-05 14:00:53 +08:00
Layout.js 里面获取 user 数据时,刷新 user 就会出现 undefine ,代码如下,请问这个问题如何处理呢?
```
import Meta from "./Meta";
import {Container, Nav, Navbar, NavDropdown} from "react-bootstrap";
import {useContext} from "react";
import {UserContext} from "../utils/userContenxt";
import jsCookie from "js-cookie";
import Router from "next/router";

export const Layout = ({children}) => {
const {user} = useContext(UserContext)
if (user === undefined) return (<>
<Meta/>
<Container>{children}</Container>
</>)
const {menu} = user

function handleLogout() {
localStorage.removeItem('u')
jsCookie.set('token', '')
Router.push('/login')
}

return (<>
<Meta/>
<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
<Container>
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav"/>
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
{menu.map(item => (<NavDropdown key={item.id} title={item.name} id="collasible-nav-dropdown">
{item.Children.map(item => (item.divide === 1 ? <NavDropdown.Divider/> : <NavDropdown.Item onClick={() => Router.push(item.path)}>{item.name}</NavDropdown.Item>))}
</NavDropdown>))}
</Nav>
<Nav>
<Nav.Link eventKey={2} href="#memes">
{user.u.uname}
</Nav.Link>
<Nav.Link onClick={() => handleLogout()}>退出</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
{children}
</>)
}
```
wiluxy
2021-12-05 18:57:56 +08:00
把数据存在 localStorage 里面,初始化的时候恢复呗
sciel
2021-12-05 19:32:09 +08:00
@wiluxy 浏览器刷新后会从服务端重新渲染,在服务端时拿不到 localStorage 里面的数据。
codexian
2021-12-05 20:52:26 +08:00
@sciel 用 redux 做数据同构
find456789
2021-12-06 01:01:01 +08:00
丢个复现的项目地址
wequart
2021-12-06 09:29:00 +08:00
把数据转成 query string 在 URL 里, 后端不就能拿得到了吗
dany813
2021-12-06 10:36:44 +08:00
放在本地?
sciel
2021-12-06 14:25:01 +08:00
@find456789
@wequart
@dany813
@codexian
多谢大家的回复,我想了一下,后台 cms 没必要服务端渲染,使用 SWR 客服端渲染就好了。一开始就不应该使用服务端渲染,没办法刚学 react 是要走点弯路。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/820147

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX