Reactjs 启动时未定义useLocation钩子:TypeError:无法读取属性';地点';未定义的
我正在编写一个typescript React应用程序,它将让用户登录并更新Reactjs 启动时未定义useLocation钩子:TypeError:无法读取属性';地点';未定义的,reactjs,typescript,react-router,react-hooks,Reactjs,Typescript,React Router,React Hooks,我正在编写一个typescript React应用程序,它将让用户登录并更新仪表板组件,以显示用户信息,例如他们的访问令牌和名称。我正在使用useLocation钩子在LoginCallback组件中传递获取请求的状态,以在仪表板组件中显示它 我遇到的问题是,启动时仪表板组件不会呈现,因为状态未定义,因为它尚未通过LoginCallback组件传递,这给了我一个TypeError:无法读取未定义的属性“location” 我想知道是否有办法为状态指定默认值。已验证的值,如有任何帮助,将不胜感激!
仪表板
组件,以显示用户信息,例如他们的访问令牌和名称。我正在使用useLocation
钩子在LoginCallback
组件中传递获取请求的状态,以在仪表板组件中显示它
我遇到的问题是,启动时仪表板组件不会呈现,因为状态未定义,因为它尚未通过LoginCallback
组件传递,这给了我一个TypeError:无法读取未定义的属性“location”
我想知道是否有办法为状态指定默认值。已验证的值,如有任何帮助,将不胜感激!组件的代码如下所示:
Index.tsx:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
从“React”导入React;
从“react dom”导入react dom;
导入“./index.css”;
从“./App”导入应用程序;
从“/reportWebVitals”导入reportWebVitals;
导入'bootstrap/dist/css/bootstrap.css';
ReactDOM.render(
}
{window.location.href='http://localhost:9090/oauth/authorize?response_type=code&client_id=client2&scope=read“;返回null;}}/>
);
}
导出默认应用程序;
Dashboard.js:
import React from 'react';
import {useLocation} from 'react-router-dom';
const Dashboard = () => {
const {state} = useLocation();
// COULD USE REDUX TO STORE USER INFO ACROSS COMPONENTS
return (
<div>
<p> Dashboard </p>
{ state.authenticated ?
<div>
<p>Authenticated</p>
<p> stored access token: {state.access_token} </p>
<p> refresh token: {state.refresh_token}</p>
<p> user: {state.user.user_name}</p>
</div>
:
<p>Not Authenticated</p>
}
</div>
);
}
export default Dashboard;
从“React”导入React;
从'react router dom'导入{useLocation};
常量仪表板=()=>{
const{state}=useLocation();
//可以使用REDUX跨组件存储用户信息
返回(
仪表板
{state.authenticated?
认证
存储的访问令牌:{state.access_token}
刷新令牌:{state.refresh_-token}
用户:{state.user.user\u name}
:
未经认证
}
);
}
导出默认仪表板;
LoginCallback.tsx:
import React, { FC, useEffect } from "react";
import { RouteComponentProps, useHistory } from "react-router-dom";
import jwt_decode from "jwt-decode";
const LoginCallback: FC<RouteComponentProps> = ({ location }) => {
const history = useHistory();
useEffect(() => {
const code = (location.search.match(/code=([^&]+)/) || [])[1];
const qParams = [
`grant_type=authorization_code`,
`scope=read`,
`code=${code}`
].join("&");
fetch(`http://localhost:9090/oauth/token?${qParams}`, {
// credentials: "include",
method: 'POST',
headers: {
'Authorization': 'Basic Y2xpZW50MjpzZWNyZXQy'
}})
.then(res => res.json())
.then(response => {
var decode = jwt_decode(response.access_token);
history.push({pathname: '/', state: {
authenticated: true,
user: decode,
access_token: response.access_token,
token_type: response.token_type,
refresh_token: response.refresh_token,
expires_in: response.expires_in,
scope: response.scope
}});
console.log(response);
})
.catch(console.error);
}, []);
return null;
};
export default LoginCallback;
import React,{FC,useffect}来自“React”;
从“react router dom”导入{RouteComponentProps,useHistory};
从“jwt解码”导入jwt_解码;
const LoginCallback:FC=({location})=>{
const history=useHistory();
useffect(()=>{
常量代码=(location.search.match(/code=([^&]+)/)| |[])[1];
常数qParams=[
`授权类型=授权代码`,
`范围=读取`,
`代码=${code}`
].加入(“&”);
取回(`http://localhost:9090/oauth/token?${qParams}`{
//证书:“包括”,
方法:“POST”,
标题:{
“授权”:“基本Y2xpZW50MjpzZWNyZXQy”
}})
.then(res=>res.json())
。然后(响应=>{
var decode=jwt_decode(response.access_令牌);
history.push({pathname:'/',状态:{
对,,
用户:解码,
访问令牌:response.access\u令牌,
令牌类型:response.token类型,
刷新\u令牌:response.refresh\u令牌,
expires\u in:response.expires\u in,
范围:response.scope
}});
控制台日志(响应);
})
.catch(控制台错误);
}, []);
返回null;
};
导出默认LoginCallback;
这是因为您在
包装器之外使用了
组件
useLocation
钩子需要在
组件的子组件中调用
已编辑
const Dashboard = () => {
const { state } = useLocation();
// COULD USE REDUX TO STORE USER INFO ACROSS COMPONENTS
return (
<div>
<p> Dashboard </p>
{ state && state.authenticated ? (
<div>
<p>Authenticated</p>
<p> stored access token: {state.access_token} </p>
<p> refresh token: {state.refresh_token}</p>
<p> user: {state.user.user_name}</p>
</div>
) : (
<p>Not Authenticated</p>
)}
</div>
);
};
常量仪表板=()=>{
const{state}=useLocation();
//可以使用REDUX跨组件存储用户信息
返回(
仪表板
{state&&state.authenticated(
认证
存储的访问令牌:{state.access_token}
刷新令牌:{state.refresh_-token}
用户:{state.user.user\u name}
) : (
未经认证
)}
);
};
Hi Taghi,谢谢您的回复!我将仪表板组件移动到路由器包装器中,但仍然得到TypeError:无法读取未定义的属性“authenticated”
这是另一个问题。您需要检查是否正在将状态传递到位置
,或者是否是true,当用户登录时,我正在从LoginCallback组件传递状态,但启动时尚未传递,所以我需要传入一个初始值或设置一个默认值或其他什么,但我不确定如何做,只需添加另一个检查state
,就像我上面提到的那样。如果答案对你有帮助的话,试着接受这个答案,那就行了!非常感谢你我真的很感激
const Dashboard = () => {
const { state } = useLocation();
// COULD USE REDUX TO STORE USER INFO ACROSS COMPONENTS
return (
<div>
<p> Dashboard </p>
{ state && state.authenticated ? (
<div>
<p>Authenticated</p>
<p> stored access token: {state.access_token} </p>
<p> refresh token: {state.refresh_token}</p>
<p> user: {state.user.user_name}</p>
</div>
) : (
<p>Not Authenticated</p>
)}
</div>
);
};