V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sciel
V2EX  ›  程序员

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

  •  
  •   sciel · 2021-12-05 13:57:19 +08:00 · 1291 次点击
    这是一个创建于 871 天前的主题,其中的信息可能已经有所发展或是发生改变。

    _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}
        </>)
    }
    
    8 条回复    2021-12-06 14:25:01 +08:00
    sciel
        1
    sciel  
    OP
       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
        2
    wiluxy  
       2021-12-05 18:57:56 +08:00
    把数据存在 localStorage 里面,初始化的时候恢复呗
    sciel
        3
    sciel  
    OP
       2021-12-05 19:32:09 +08:00
    @wiluxy 浏览器刷新后会从服务端重新渲染,在服务端时拿不到 localStorage 里面的数据。
    codexian
        4
    codexian  
       2021-12-05 20:52:26 +08:00
    @sciel 用 redux 做数据同构
    find456789
        5
    find456789  
       2021-12-06 01:01:01 +08:00
    丢个复现的项目地址
    wequart
        6
    wequart  
       2021-12-06 09:29:00 +08:00
    把数据转成 query string 在 URL 里, 后端不就能拿得到了吗
    dany813
        7
    dany813  
       2021-12-06 10:36:44 +08:00
    放在本地?
    sciel
        8
    sciel  
    OP
       2021-12-06 14:25:01 +08:00
    @find456789
    @wequart
    @dany813
    @codexian
    多谢大家的回复,我想了一下,后台 cms 没必要服务端渲染,使用 SWR 客服端渲染就好了。一开始就不应该使用服务端渲染,没办法刚学 react 是要走点弯路。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1052 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 252ms · UTC 22:12 · PVG 06:12 · LAX 15:12 · JFK 18:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.