[英]Not able to set state of new component when history.push() in React
我正在嘗試使用 OAuth2 授權代碼授權類型為 React 前端創建登錄流。 我已經能夠將用戶定向到身份驗證服務器的登錄頁面,成功登錄后重定向到我的反應前端: "http:localhost:3000/oauth_callback?code={auth_code}"
然后呈現 LoginCallback 組件,該組件采用 auth_code 值並發送 POST fetch 請求以獲取訪問令牌,響應將如下所示:
{
access_token: "640f3dce-11c6-45fe-8984-517ecce471ae",
token_type: "bearer",
expires_in: 37822,
scope: "read"
}
返回后,我嘗試使用 history.push() 將用戶導航到 Dashboard 組件,響應數據處於 Dashboards 狀態。
我遇到的問題是我無法使用獲取請求的響應來設置狀態,並且因為 LoginCallback 組件是從身份驗證服務器重定向到的,所以沒有父組件可以將狀態發送回。
登錄回調:
import React, { FC, useEffect } from "react";
import { RouteComponentProps, useHistory } from "react-router-dom";
import Dashboard from "./components/Dashboard";
const LoginCallback: FC<RouteComponentProps> = ({ location }) => {
const history = useHistory();
var response = {
access_token: '',
token_type: '',
expires_in: 0,
scope: ''
}
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(res => console.log(res))
.then(res => JSON.stringify(res))
.then(res => {
console.log(`json.stringify(): ${JSON.stringify(res)}`); // returns undefined
console.log(`json.parse(): ${JSON.parse(res)}`);
response = JSON.parse(res); // returns syntaxError: Unexpected token u in JSON at position 0
history.push({pathname: '/dashboard', state: {
authenticated: true,
access_token: response.access_token,
token_type: response.token_type,
expires_in: response.expires_in,
scope: response.scope
}});
})
.catch(console.error);
}, []);
return null;
};
export default LoginCallback;
儀表盤:
import { render } from '@testing-library/react';
import React, {useState} from 'react';
const Dashboard = () => {
const [state, setAllValues] = useState({
authenticated: false,
access_token: '',
token_type: '',
expires_in: 0,
scope: ''
});
const changeHandler = e => {
setAllValues({...state, [e.target.name]: e.target.value})
}
return (
<div>
{ state.authenticated ? <a href="/login">Login Here</a> : <a href="/logout">Logout</a> }
<p> Dashboard </p>
<p> Authenticated: {state.authenticated}</p>
{ state.authenticated ?
<p> stored access token: {state.access_token} </p>
:
null
}
</div>
);
}
export default Dashboard;
在您的儀表板組件中考慮添加以下代碼
import { useLocation } from "react-router-dom";
function Dashboard() {
const { state } = useLocation();
return <div>{JSON.stringify(state)}</div>;
}
我相信這將使您能夠訪問您傳入的狀態。如果沒有共享您的儀表板代碼的相關部分,我們可以看看。
對於您的 fetch 調用,請嘗試:
fetch(`http://localhost:9090/oauth/token?${qParams}`, {
// credentials: "include",
method: 'POST',
headers: {
'Authorization': 'Basic Y2xpZW50MjpzZWNyZXQy'
}
})
.then(res => res.json())
.then(response => {
history.push({pathname: '/dashboard', state: {
authenticated: true,
access_token: response.access_token,
token_type: response.token_type,
expires_in: response.expires_in,
scope: response.scope
}});
})
.catch(console.error);
我發現 axios 更易於使用。
useHistory()
僅適用於HOC為BrowserRouter
那些組件
使用此代碼導入Dashboard
<BrowserRouter>
<Switch>
<Route path="/dashboard" exact component={Dashboard} />
</Switch>
</BrowserRouter>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.