检查身份验证后反应组件不呈现
React component not rendering after checking for Authentication
所以基本上我正在尝试为我的应用程序创建一个受保护的路由,并且我有另一个功能可以检查服务器 API 客户端是否通过了正确的身份验证。
不幸的是,由于 React Hooks 的工作方式,状态不会直接更新,如果我在用户未通过身份验证时尝试进行重定向,它只会将我发送到那里。
因此,当您重新加载页面时,由于状态也已重置,因此在第一次呈现时它会将我视为未登录(即使我已登录)并将我发送到登录页面。
所以我想的是我可以等待直到它得到响应然后用 isAuth(ctx).then(...)
渲染,但是,它只是不渲染任何东西。
这是我的路由器结构:
<BrowserRouter>
<AppContext.Provider value={ctx}>
<Route path="/dashboard">
<Switch>
<LoginRoute exact path="/dashboard/login" component={LogInDash} />
<ProtectedRoute exact path="/dashboard/create" component={CreateProperty} />
<ProtectedRoute exact path="/dashboard/list" component={ListDash} />
<ProtectedRoute exact path="/dashboard/edit/:id" component={EditProperty} />
<ProtectedRoute exact path="/dashboard/delete/:id" component={DeleteProperty} />
</Switch>
</Route>
</AppContext.Provider>
</BrowserRouter>
这里是从 API:
获取的函数
export const isAuth = async (ctx: React.ComponentState): Promise<boolean> => {
const fetchRes = fetch(`${APIURL}/api/auth`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
})
.then((res) => {
res.json();
if (res.status === 200) {
ctx.auth.set(true);
console.log('successful verification');
return true;
} else {
ctx.auth.set(false);
console.log('Token not verified');
return false;
}
})
.catch((error) => {
console.log(error);
return false;
});
return fetchRes;
};
最后,这里是 ProtectedRouter 代码:
export function ProtectedRoute({ component: Component, ...rest }: any): any {
const ctx = React.useContext(AppContext);
return (
<Route
{...rest}
render={(props) => {
isAuth(ctx);
/* isAuth(ctx).then((res) => { */
if (ctx.auth.get) {
return <Component {...rest} {...props} />;
} else {
/* return <Unauthorized />; */
return <Redirect to="/dashboard/login" />;
/* window.location.href = '/dashboard/login'; */
}
/* }); */
}}
/>
);
}
我觉得我只是遗漏了一些愚蠢的东西,或者我试图应用的概念有一些错误。
感谢您阅读到这里!
// NOTE: Is this firing correctly.. doesn't seem to fire if signed in .... and then try to go to profile or inventory page directly .... always redirects to '/' it seems
const AuthedRoute = ({ component: Component, user, ...rest }) => (
<Route
{...rest}
render={(props) =>
user.authenticated === null ? null : user.authenticated ? <Component {...props} /> : <Redirect to="/" />
}
/>
);
我会在 useEffect
挂钩中引入新的 isReady
状态和 await
用于身份验证。例如,在未准备好之前,应用程序可以显示正在加载 <span>
。
看我的建议如下:
export function ProtectedRoute({ component: Component, ...rest }: any): any {
const ctx = React.useContext(AppContext);
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const runAuth = async () => {
await isAuth(ctx);
setIsReady(true);
}
runAuth();
}, [])
return (
<Route
{...rest}
render={(props) => {
if (!isReady} {
return <span>Loading ...</span>
}
if (ctx.auth.get) {
return <Component {...rest} {...props} />;
} else {
/* return <Unauthorized />; */
return <Redirect to="/dashboard/login" />;
/* window.location.href = '/dashboard/login'; */
}
/* }); */
}}
/>
);
}
建议阅读 Using the Effect Hook。
所以基本上我正在尝试为我的应用程序创建一个受保护的路由,并且我有另一个功能可以检查服务器 API 客户端是否通过了正确的身份验证。 不幸的是,由于 React Hooks 的工作方式,状态不会直接更新,如果我在用户未通过身份验证时尝试进行重定向,它只会将我发送到那里。 因此,当您重新加载页面时,由于状态也已重置,因此在第一次呈现时它会将我视为未登录(即使我已登录)并将我发送到登录页面。
所以我想的是我可以等待直到它得到响应然后用 isAuth(ctx).then(...)
渲染,但是,它只是不渲染任何东西。
这是我的路由器结构:
<BrowserRouter>
<AppContext.Provider value={ctx}>
<Route path="/dashboard">
<Switch>
<LoginRoute exact path="/dashboard/login" component={LogInDash} />
<ProtectedRoute exact path="/dashboard/create" component={CreateProperty} />
<ProtectedRoute exact path="/dashboard/list" component={ListDash} />
<ProtectedRoute exact path="/dashboard/edit/:id" component={EditProperty} />
<ProtectedRoute exact path="/dashboard/delete/:id" component={DeleteProperty} />
</Switch>
</Route>
</AppContext.Provider>
</BrowserRouter>
这里是从 API:
获取的函数export const isAuth = async (ctx: React.ComponentState): Promise<boolean> => {
const fetchRes = fetch(`${APIURL}/api/auth`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
})
.then((res) => {
res.json();
if (res.status === 200) {
ctx.auth.set(true);
console.log('successful verification');
return true;
} else {
ctx.auth.set(false);
console.log('Token not verified');
return false;
}
})
.catch((error) => {
console.log(error);
return false;
});
return fetchRes;
};
最后,这里是 ProtectedRouter 代码:
export function ProtectedRoute({ component: Component, ...rest }: any): any {
const ctx = React.useContext(AppContext);
return (
<Route
{...rest}
render={(props) => {
isAuth(ctx);
/* isAuth(ctx).then((res) => { */
if (ctx.auth.get) {
return <Component {...rest} {...props} />;
} else {
/* return <Unauthorized />; */
return <Redirect to="/dashboard/login" />;
/* window.location.href = '/dashboard/login'; */
}
/* }); */
}}
/>
);
}
我觉得我只是遗漏了一些愚蠢的东西,或者我试图应用的概念有一些错误。
感谢您阅读到这里!
// NOTE: Is this firing correctly.. doesn't seem to fire if signed in .... and then try to go to profile or inventory page directly .... always redirects to '/' it seems
const AuthedRoute = ({ component: Component, user, ...rest }) => (
<Route
{...rest}
render={(props) =>
user.authenticated === null ? null : user.authenticated ? <Component {...props} /> : <Redirect to="/" />
}
/>
);
我会在 useEffect
挂钩中引入新的 isReady
状态和 await
用于身份验证。例如,在未准备好之前,应用程序可以显示正在加载 <span>
。
看我的建议如下:
export function ProtectedRoute({ component: Component, ...rest }: any): any {
const ctx = React.useContext(AppContext);
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const runAuth = async () => {
await isAuth(ctx);
setIsReady(true);
}
runAuth();
}, [])
return (
<Route
{...rest}
render={(props) => {
if (!isReady} {
return <span>Loading ...</span>
}
if (ctx.auth.get) {
return <Component {...rest} {...props} />;
} else {
/* return <Unauthorized />; */
return <Redirect to="/dashboard/login" />;
/* window.location.href = '/dashboard/login'; */
}
/* }); */
}}
/>
);
}
建议阅读 Using the Effect Hook。