首页 > 解决方案 > 问题持续存在全球状态 ReactJS

问题描述

我正在做一个项目,我使用 ReactJS 中可用的东西实现了全局状态,没有使用第三方库。

当我设置全局状态时,我还将它添加到本地存储中,因此如果浏览器重新加载,我的想法是我将能够从本地存储中提取数据并将其设置为全局状态,但这不会t 似乎正在工作,因为在页面重新加载后尝试访问全局状态内的属性时,我不断返回一个未定义的错误。

我的 GlobalStateProvider 如下:

import React, {createContext, useState, useContext, Dispatch, SetStateAction, useEffect} from "react";
export interface GlobalStateInterface {
    trial: {
        in_trial: boolean,
        days_of_trial_remaining: number
    }
    payment_failed: {
        last_payment_failed: boolean,
        payment_time_required: number,
        last_payment_failed_reason: string,
        payment_required: boolean
    }
}

const GlobalStateContext = createContext({
    globalState: {} as Partial<GlobalStateInterface>,
    setGlobalState: {} as Dispatch<SetStateAction<Partial<GlobalStateInterface>>>,
});

const GlobalStateProvider = ({
                                 children,
                                 value = {} as GlobalStateInterface,
                             }: {
    children: React.ReactNode;
    value?: Partial<GlobalStateInterface>;
}) => {
    const [globalState, setGlobalState] = useState(value);

    return (
        <GlobalStateContext.Provider value={{ globalState, setGlobalState }}>
            {children}
        </GlobalStateContext.Provider>
    );
};

const useGlobalState = () => {
    const context = useContext(GlobalStateContext);
    if (!context) {
        throw new Error("useGlobalState must be used within a GlobalStateContext");
    }
    return context;
};

export { GlobalStateProvider, useGlobalState };

我创建了一个 BaseComponent ,我希望我可以使用它来检查 localStorage 是否包含全局状态提供程序,如果是,则将其加载到全局状态中,因此该组件包含以下内容:

import * as React from "react";
import {useEffect} from "react";
import {useGlobalState} from "./GlobalStateProvider";

export default function BaseComponent(props) {

    const { setGlobalState } = useGlobalState();
    useEffect(() => {

        let tempGlobalStorage = localStorage.getItem("global_state");

        console.log("Temp Global State: ", tempGlobalStorage);
        if (tempGlobalStorage !== null) {
            const tempGlobalStorageJson = JSON.parse(tempGlobalStorage);
            setGlobalState({...tempGlobalStorageJson});
        }

    }, []);

    return (
        <>
            {props.children}
        </>
    )
}

我的 App.js 如下所示:(我只显示 App.js 中返回的内容,因为我认为没有任何相关性)

return (
        <Elements stripe={stripePromise}>
            <GlobalStateProvider>
                <BaseComponent>
                    <BrowserRouter>
                        <div className='h-full'>
                            <Switch>
                                <Route path="/" render={(props) => <Login {...props}  /> } exact />
                                <Route path="/login/:msg?/:redirect?" render={(props) => <Login {...props} /> } exact />
                                <Route path="/choose-plan" render={() => <ChoosePlan /> } exact />
                                <Route path="/signup/:plan" render={(props) => <SignUp {...props} /> } exact />
                                <Route path="/dashboard" render={() => <Dashboard  /> } exact />
                                <Route path="/project-settings/:project_id" render={(props) => <ProjectSettings {...props} /> } />
                                <Route path="/settings" render={() => <Settings /> } exact />
                                <Route path='/add-project' render={() => <AddProject  /> } exact />
                                <Route path='/final-project-setup/:platform/:project_id/:api_key' render={(props) => <FinalProjectSetup {...props}  /> } />
                                <Route path='/crash-details/:project_id/:project_type/:crash_group_id?/:comment_id?' render={(props) => <CrashDetails {...props} /> } />
                                <Route path='/team-members' render={() => <ManageTeamMembers  /> } />
                                <Route path='/add-team-member' render={() => <AddTeamMember  /> } />
                                <Route path='/register-new-user/:invite_params?' render={(props) => <RegisterNewUser {...props} /> } />
                                <Route path='/account-billing' render={() => <AccountAndBilling /> } exact />
                                <Route path='/forgotten-password' render={() => <ForgottenPassword /> } exact />
                                <Route path='/reset-password/:resetPasswordData' render={(props) => <ResetPassword {...props} /> } />

                                <Route path='/status' render={() => <Status /> } />
                                <Route render={() => <NotFound  />}/>
                            </Switch>
                        </div>
                    </BrowserRouter>
                </BaseComponent>
            </GlobalStateProvider>
        </Elements>
    );

正如您在 BaseComponent 中看到的那样,我注销了 localStorage 中的内容,它不会在页面重新加载时输出任何内容,就好像我在其中一个路由组件中访问全局状态的位置在 BaseComponent 触发 useEffect 之前被触发.

下面是设置状态和全局存储的示例:

const tempGlobalState = globalState;
                tempGlobalState.trial = {
                    in_trial: response.data.in_trial,
                    days_of_trial_remaining: response.data.in_trial ? response.data.trial_days_remaining : null
                }

                tempGlobalState.payment_failed = {
                    last_payment_failed: response.data.last_payment_failed,
                    last_payment_failed_reason: response.data.last_payment_failed_reason,
                    payment_time_required: response.data.payment_time_required,
                    payment_required: false //Still within the 7 day grace period for non payment
                }
                /*tempGlobalState.trial.in_trial = response.data.in_trial;
                if (response.data.in_trial)
                {
                    tempGlobalState.trial.days_of_trial_remaining = response.data.trial_days_remaining;
                }*/
                localStorage.setItem("global_state", JSON.stringify(tempGlobalState));
                setGlobalState({...tempGlobalState});

标签: reactjslocal-storageglobal-state

解决方案


推荐阅读