Javascript React useContext在延迟后给出输出

Javascript React useContext在延迟后给出输出,javascript,reactjs,react-redux,react-router,Javascript,Reactjs,React Redux,React Router,我需要使用来自useContext的数据来验证登录的用户是否为Admin。但它首先给出“未定义”值,然后在延迟5秒后给出实际值。 但到那时,代码就中断了,因为它无法处理“未定义”代码 import React,{useContext,useffect}来自“React”; 从'react router dom'导入{useHistory}; 从“../../context/AuthContext”导入{AuthContext}; 常量管理=()=>{ const history=useHisto

我需要使用来自useContext的数据来验证登录的用户是否为Admin。但它首先给出“未定义”值,然后在延迟5秒后给出实际值。 但到那时,代码就中断了,因为它无法处理“未定义”代码

import React,{useContext,useffect}来自“React”;
从'react router dom'导入{useHistory};
从“../../context/AuthContext”导入{AuthContext};
常量管理=()=>{
const history=useHistory();
const{userData}=useContext(AuthContext);
log(userData);//*******这首先给出了{token:undefined,user:undefined}
/*****************************然后在5-10秒延迟后给出实际数据
*{令牌:“eyJhbGciOiJIUzI”,用户:{…}
令牌:“eyJhbGciOiJIUzI”
用户:
伊萨明:是的
__v:0
_id:“5eea03a736b70722c83a7b63”
*******************************************************************/
//我想获取“isAdmin”//以便我可以处理进一步的代码
如果(!userData.user.isAdmin){
历史。推送(“/”);
};
返回管理面板
};

我需要使用异步/等待吗?因为我尝试在自定义异步函数中执行此操作,但它引发了另一个错误,我们无法在非反应函数中使用useContext

您可以设置
useffect
钩子,在状态(userData)更改时执行副作用(重定向到“/”):

替换:

if (!userData.user.isAdmin) {
  history.push("/");
}
与:

更多关于

然后,您可以根据不同的情况返回不同的组件:

if (!userData) return <p>Loading</p>;
if (!userData.user.isAdmin) return <p>You are not an admin. Redirecting...</p>;
return <h1>Admin Panel</h1>;
if(!userData)返回加载;
如果(!userData.user.isAdmin)返回您不是管理员。重定向…

; 返回管理面板;
< /代码> 您可能需要考虑扩展路由组件并在AuthCurror中添加<代码>加载< /代码>状态(并且可能是错误),同时进行身份验证。

AdminOnlyRoute.js

从“React”导入React;
从“react router dom”导入{Redirect,useLocation,Route};
从“../../context/AuthContext”导入{AuthContext};
常量管理员权限=(道具)=>{
//给上下文一个加载和/或错误状态
const{userData,loading,error}=useContext(AuthContext);
如果(装载){
//也许是加载器?
返回验证。。。
}
如果(错误){
返回身份验证错误。
}
if(userData&!userData.user.isAdmin)
返回(
);
返回;
};
导出默认管理员列表;
您可以这样使用此组件:



我从评论中汲取了一些想法,并找到了解决办法。 这也很好:

import React, { useContext, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { AuthContext } from '../../context/AuthContext';
import AdminPanel from './AdminPanel';

const Admin = () => {
    const token = localStorage.getItem('auth-token');
    const history = useHistory();
    const { userData } = useContext(AuthContext);

    //send item to backend
    const saveNewItem = async (data) => {
        const url = "http://localhost:5000/api/items";
        try {
            const res = await axios.post(url, data, {
                headers: { "x-auth-token": token }
            });
            console.log(res.data);    
        } catch (error) {
            console.log(error.response);
        }
    };

    /********************************
     * Handling Authentication logic
     ********************************/
    };
    if (!token) {
        history.push("/");
    };
    /********************************
     * Handling Authentication logic
     ********************************/

    return <div>
        {
            userData.user !== undefined && userData.user.isAdmin 
            ? <AdminPanel saveNewItem={saveNewItem}/>
            :
            <div className="container p-5 text-center">
            <div class="spinner-border text-light" role="status">
                <span class="sr-only">Loading...</span>
            </div>
            </div>   
        }
        {/* <AdminPanel saveNewItem={saveNewItem}/> */}
    </div>

};
export default Admin;
import React,{useContext,useffect}来自“React”;
从'react router dom'导入{useHistory};
从“../../context/AuthContext”导入{AuthContext};
从“/AdminPanel”导入AdminPanel;
常量管理=()=>{
const-token=localStorage.getItem('auth-token');
const history=useHistory();
const{userData}=useContext(AuthContext);
//将项目发送到后端
const saveNewItem=async(数据)=>{
常量url=”http://localhost:5000/api/items";
试一试{
const res=等待axios.post(url、数据、{
标题:{“x-auth-token”:token}
});
console.log(res.data);
}捕获(错误){
console.log(error.response);
}
};
/********************************
*处理身份验证逻辑
********************************/
};
如果(!令牌){
历史。推送(“/”);
};
/********************************
*处理身份验证逻辑
********************************/
返回
{
userData.user!==未定义&&userData.user.isAdmin
? 
:
加载。。。
}
{/*  */}
};
导出默认管理员;
我希望这对我来说是有意义的。
(如果这方面的安全性有任何问题,请告诉我)

在哪里提取?我的意思是,5秒后它从哪里来?console.log(userData)在每次页面呈现时显示两次。当页面尝试获取身份验证用户数据时,您可以说“正在加载”。函数getPage(userData){if(!userData.user){return loading……}并在返回中使用它,例如
return{getPage(userData)}
但这并不能解决限制其他人手动路由到/admin的问题。在这种情况下,他们可以手动转到admin页面。我还可以做些什么吗?如果没有用户数据(获取时)或用户不是管理员,您应该返回一些加载组件或null:
如果(!userData | |)(userData.user&!userData.user.isAdmin))return null;
谢谢。我根据您的建议发布了一个答案。您能告诉我这在生产中是否有效吗?
if (!userData) return <p>Loading</p>;
if (!userData.user.isAdmin) return <p>You are not an admin. Redirecting...</p>;
return <h1>Admin Panel</h1>;
import React, { useContext, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { AuthContext } from '../../context/AuthContext';
import AdminPanel from './AdminPanel';

const Admin = () => {
    const token = localStorage.getItem('auth-token');
    const history = useHistory();
    const { userData } = useContext(AuthContext);

    //send item to backend
    const saveNewItem = async (data) => {
        const url = "http://localhost:5000/api/items";
        try {
            const res = await axios.post(url, data, {
                headers: { "x-auth-token": token }
            });
            console.log(res.data);    
        } catch (error) {
            console.log(error.response);
        }
    };

    /********************************
     * Handling Authentication logic
     ********************************/
    };
    if (!token) {
        history.push("/");
    };
    /********************************
     * Handling Authentication logic
     ********************************/

    return <div>
        {
            userData.user !== undefined && userData.user.isAdmin 
            ? <AdminPanel saveNewItem={saveNewItem}/>
            :
            <div className="container p-5 text-center">
            <div class="spinner-border text-light" role="status">
                <span class="sr-only">Loading...</span>
            </div>
            </div>   
        }
        {/* <AdminPanel saveNewItem={saveNewItem}/> */}
    </div>

};
export default Admin;