React 应用页面路由问题 – 用户成功登录后

huangapple go评论61阅读模式
英文:

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) =&gt; {
  ...

  try {
    const { account, idToken } = await msalInstance.loginPopup(scopes);
    const { name, username } = account;
    const userid = username.slice(0, username.indexOf(&quot;@&quot;));

    const loginData = {
      auth_token: idToken,
      user: {
        name,
        id: userid,
        email: username,
      },
    };

    ...
    
    sessionStorage.setItem(&quot;currentUser&quot;, JSON.stringify(loginData));
    dispatch({ type: &quot;LOGIN_SUCCESS&quot;, payload: loginData });
    
    return { loginData, error: null }; // &lt;-- return value
  } catch (error) {
    dispatch({ type: &quot;LOGIN_ERROR&quot;, error });
    return { loginData: null, error }; // &lt;-- return value
  }
};
const handleLogin = async () =&gt; {
  const { loginData } = await AuthService(dispatch);

  if (loginData &amp;&amp; loginData.auth_token) { // or loginData?.auth_token
    navigate(&quot;/dashboard&quot;, { replace: true });
  }
};

huangapple
  • 本文由 发表于 2023年2月16日 12:38:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75467913.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定