我正在做一个项目,我使用 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});