英文:
React app page routing issue post successful user login
问题
以下是你要翻译的内容:
I have a react app where I use the useContext
and useReducer
hooks for the login and storage. While the login part works, what I want achieve is to redirect user to a specific page post successful login. I am using react-router@6
and tried to use useNavigate()
to navigate user to a particular route though it doesn't seem to work.
const AuthService = async (dispatch) => {
const MSAL_CONFIG = {} // populate MSAL config for Microsoft Graph API for AD auth
const msalInstance = new msal.PublicClientApplication(MSAL_CONFIG);
try {
const loginResponse = await msalInstance.loginPopup(scopes);
var username = loginResponse.account.username;
var userid = username.slice(0, username.indexOf("@"));
const loginData = {
auth_token: loginResponse.idToken,
user: {
name: loginResponse.account.name,
id: userid,
email: username,
},
};
const sessionData = {
user_id: userid,
id_token: loginResponse.idToken,
access_token: loginResponse.accessToken,
}
sessionStorage.setItem("currentUser", JSON.stringify(loginData));
dispatch({ type: "LOGIN_SUCCESS", payload: loginData });
return { loginData: loginData, error: null };
// dispatch({ type: 'LOGIN_SUCCESS', payload: loginData });
//sessionStorage.setItem('currentUser', JSON.stringify(data));
} catch (err) {
console.log("+++ Login error : ", err);
dispatch({ type: "LOGIN_ERROR", error: err });
return { loginData: null, error: err };
}
};
In my header.jsx
, I have below code to handle the login button. It makes a call to the above AuthService
. The code post AuthService()
call, i.e. the if block, doesn't take effect, so the user never gets redirected to the dashboard page.
const handleLogin = async () => {
await AuthService(dispatch)
console.log("userDetails.token : " + userDetails.token)
if (Boolean(userDetails.token)) {
navigate("/dashboard");
}
};
英文:
I have a react app where I use the useContext
and useReducer
hooks for the login and storage. While the login part works, what I want achieve is to redirect user to a specific page post successful login. I am using react-router@6
and tried to use useNavigate()
to navigate user to particular route though it doesn't seem to work.
const AuthService = async (dispatch) => {
const MSAL_CONFIG = {} // populate MSAL config for Microsoft Graph API for AD auth
const msalInstance = new msal.PublicClientApplication(MSAL_CONFIG);
try {
const loginResponse = await msalInstance.loginPopup(scopes);
var username = loginResponse.account.username;
var userid = username.slice(0, username.indexOf("@"));
const loginData = {
auth_token: loginResponse.idToken,
user: {
name: loginResponse.account.name,
id: userid,
email: username,
},
};
const sessionData = {
user_id: userid,
id_token: loginResponse.idToken,
access_token: loginResponse.accessToken,
}
sessionStorage.setItem("currentUser", JSON.stringify(loginData));
dispatch({ type: "LOGIN_SUCCESS", payload: loginData });
return { loginData: loginData, error: null };
// dispatch({ type: 'LOGIN_SUCCESS', payload: loginData });
//sessionStorage.setItem('currentUser', JSON.stringify(data));
} catch (err) {
console.log("+++ Login error : ", err);
dispatch({ type: "LOGIN_ERROR", error: err });
return { loginData: null, error: err };
}
};
In my header.jsx
, I have below code to handle the login button. It makes a call to the above AuthService
. The code post AuthService()
call, i.e. the if block, doesn't take effect, so user never gets redirected to the dashboard page.
const handleLogin = async () => {
await AuthService(dispatch)
console.log("userDetails.token : " + userDetails.token)
if (Boolean(userDetails.token)) {
navigate("/dashboard");
}
};
答案1
得分: 0
如果我理解正确,AuthService
函数最终会解析,并且分发的 LOGIN_SUCCESS
操作会更新从身份验证上下文状态中选择的 userDetails
变量,那么我认为您已经拥有所需的一切,并且接近一个可用的解决方案。问题在于在调用 handleLogin
的渲染周期中,来自回调范围的 userDetails
值是封闭的,它永远不会成为不同的值。如果在调用 handleLogin
时,userDetails.token
值为假值,它将在整个回调范围内保持为假值。
AuthService
函数似乎会返回分发的 LOGIN_SUCCESS
操作传递给存储的相同 loginData
对象。handleLogin
应该 await
此值,并有条件地导航。
const AuthService = async (dispatch) => {
...
try {
const { account, idToken } = await msalInstance.loginPopup(scopes);
const { name, username } = account;
const userid = username.slice(0, username.indexOf("@"));
const loginData = {
auth_token: idToken,
user: {
name,
id: userid,
email: username,
},
};
...
sessionStorage.setItem("currentUser", JSON.stringify(loginData));
dispatch({ type: "LOGIN_SUCCESS", payload: loginData });
return { loginData, error: null }; // <-- 返回值
} catch (error) {
dispatch({ type: "LOGIN_ERROR", error });
return { loginData: null, error }; // <-- 返回值
}
};
const handleLogin = async () => {
const { loginData } = await AuthService(dispatch);
if (loginData && loginData.auth_token) { // 或 loginData?.auth_token
navigate("/dashboard", { replace: true });
}
};
英文:
If I'm correct in understanding that this AuthService
function eventually resolves and that the dispatched LOGIN_SUCCESS
action updates the userDetails
variable that is selected from the auth context state, then I think you have all that you need and are close to a working solution. The issue is that the userDetails
value from the render cycle the handleLogin
is called in is closed over in callback scope, it will never be a different value. If the userDetails.token
value is falsey when handleLogin
is called, it will remain falsey in the entire callback scope.
The AuthService
function appears to return the same loginData
object that is passed in the dispatched LOGIN_SUCCESS
action to the store. handleLogin
should await
this value and conditionally navigate.
const AuthService = async (dispatch) => {
...
try {
const { account, idToken } = await msalInstance.loginPopup(scopes);
const { name, username } = account;
const userid = username.slice(0, username.indexOf("@"));
const loginData = {
auth_token: idToken,
user: {
name,
id: userid,
email: username,
},
};
...
sessionStorage.setItem("currentUser", JSON.stringify(loginData));
dispatch({ type: "LOGIN_SUCCESS", payload: loginData });
return { loginData, error: null }; // <-- return value
} catch (error) {
dispatch({ type: "LOGIN_ERROR", error });
return { loginData: null, error }; // <-- return value
}
};
const handleLogin = async () => {
const { loginData } = await AuthService(dispatch);
if (loginData && loginData.auth_token) { // or loginData?.auth_token
navigate("/dashboard", { replace: true });
}
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论