我正在尝试使用 Reatjs、nodejs 和 JWT 创建受保护的路由。问题是我的组件在我的 API 检查客户端令牌之前呈现。这是我正在尝试的代码:
import React, {useState, useEffect} from 'react';
import { Route, Redirect } from 'react-router-dom';
import AuthAPI from './../utils/AuthAPI';
const ProtectedRoute = ({children, ...rest}) => {
const [isAuth, setIsAuth] = useState(false);
const fetchData = async () => {
await AuthAPI.isAuth((res)=>{ //API call
setIsAuth(res);
});
}
useEffect(()=>{
fetchData();
},[]);
return (
<Route {...rest}
render={(props)=>{
return(
isAuth ? children : <Redirect to='/' />
);
}}
/>
);
};
这是 API 调用:
static isAuth(callback){ //static method from the class 'AuthAPI' imported above
const url = 'http://localhost:5000/api/Auth/checking';
const options = {
method: 'GET',
url: url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
},
data: {}
}
return axios(options)
.then((response)=>{
callback(true);
}).catch((err)=>{
callback(false);
});
}
当我加载页面时,它直接重定向,因为状态 isAuth 默认设置为 false。 我已经使用这种代码模型来显示从 API 获取的内容列表,并且运行良好。我认为这不是最好的方法,但我发现的大多数示例都没有使用实际的 API,而只是在不使用承诺的情况下伪造身份验证。
编辑 1.2:
我已经尝试过这个代码,来自 Udendu Abasili :
import React, {useState, useEffect} from 'react';
import { Route, Redirect } from 'react-router-dom';
import AuthAPI from './../utils/AuthAPI';
const ProtectedRoute = ({children, ...rest}) => {
const [isAuth, setIsAuth] = useState(false);
const [isLoaded, setIsLoaded] = useState(false)
useEffect(()=>{
let mounted = true;
AuthAPI.isAuth().then(()=>{
if (mounted) {
console.log("Worked"); //display Worked
setIsLoaded(true); // This line 1
setIsAuth(true); // This line 2
}
}).catch(()=>{
if (mounted) {
console.log("Failed");
setIsLoaded(true);
setIsAuth(false);
}
});
return () => {
mounted = false;
}
},[]);
return (
!isLoaded ?
<h5>Loading</h5> : (
<Route {...rest}
render={(props)=>{
console.log("--->",isAuth,",",isLoaded); // displays false, true
return(
isAuth ? children : <Redirect to='/' />
);
}}
/>
)
);
};
export default ProtectedRoute;
我发现了一个奇怪的错误。如果我交换注释为“第 1 行”和“第 2 行”的行,它会起作用,否则不会。
答案 0 :(得分:0)
react js 生命周期的工作方式是,返回组件在 useEffect
之前被调用(在第一次挂载时相当于 componentDidMount 的钩子)。因此,您需要创建一个加载器组件的形式(将 <Text>Loading</Text>
替换为实际的 CSS 加载器),等待您的 isAuth 函数完成。
const ProtectedRoute = ({children, ...rest}) => {
const [isAuth, setIsAuth] = useState(false);
const [loaded, setLoaded] = useState(false);
const fetchData = async () => {
//you need to add try catch here
await AuthAPI.isAuth((res)=>{ //API call
setIsAuth(res);
setLoaded(true)
});
}
useEffect(()=>{
fetchData();
},[]);
return (
loaded ?
<Text>Loading</Text> : (
<Route {...rest}
render={(props)=>{
return(
isAuth ? children : <Redirect to='/' />
);
}}
)
/>
);
};
正如您所说,这不是最好的方法。我不建议在受保护的路由组件中调用函数来检查身份验证。通常,我只是将 isAuthenticated 参数传递给 ProctectedRoute 组件,该组件在 Redux 的帮助下进行更新。你应该查一下