React JS 登录后重定向

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

React JS Redirect Upon Sign in

问题

I need my user to be redirected upon success. What I have now does not redirect but will present the success pop up message at the end of the form.

JSX 文件

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { Navigate } from 'react-router-dom';

const Login = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [loginStatus, setLoginStatus] = useState('');

  axios.defaults.withCredentials = true;

  const login = (event) => {
    event.preventDefault();

    axios
      .post('http://localhost:5000/login', {
        username: username,
        password: password,
      })
      .then((response) => {
        if (response.data.message) {
          setLoginStatus(response.data.message);
        } else {
          setLoginStatus(response.data.username);
          // 这里不能直接使用 <Navigate to="/admin/home" /> 来进行重定向
          // 你需要在组件外部使用路由来进行重定向
        }
      })
      .catch((error) => {
        console.error('Error logging in:', error);
      });
  };

  useEffect(() => {
    axios
      .get('http://localhost:5000/check-session')
      .then((response) => {
        if (response.data.loggedIn) {
          // 这里也不能直接使用 <Navigate to="/admin/home" /> 来进行重定向
          // 你需要在组件外部使用路由来进行重定向
        }
      })
      .catch((error) => {
        console.error('Error checking session:', error);
      });
  }, []);

  return (
    <div className='Login-page'>
      <h1>Login</h1>
      <form onSubmit={login}>
        <button type='submit' className='btn btn-outline-primary'>
          Login
        </button>
      </form>
      {loginStatus && <p>{loginStatus}</p>}
    </div>
  );
};

export default Login;

Server.js (Express 文件)

const express = require('express');
const app = express();
const mysql = require('mysql');
const morgan = require('morgan');
const cors = require('cors');
const session = require('express-session');

const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');

// Middleware
app.use(
  cors({
    origin: 'http://localhost:3000', // 替换为你的前端应用的 URL
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    credentials: true, // 允许携带凭证 (cookies)
  })
);
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(express.json()); // 解析 JSON 请求体
app.use(express.urlencoded({ extended: true })); // 解析 URL 编码的请求体
app.use(morgan('dev')); // 使用 Morgan 记录 HTTP 请求

// 会话设置
/* 设置 Cookie 选项 */
app.use(
  session({
    secret: 'secretKey123',
    resave: false,
    saveUninitialized: false,
    cookie: {
      secure: false, // 如果使用 HTTPS,请将此设置为 true
      maxAge: 24 * 60 * 60 * 1000, // 24 小时
    },
  })
);

// 路由

app.post('/login', (req, res) => {
  const username = req.body.username;
  const password = req.body.password;

  connection.query(
    'SELECT * FROM admin_users WHERE username = ? AND password = ?',
    [username, password],
    (error, results, fields) => {
      if (error) {
        console.error('Error executing MySQL query: ' + error.stack);
        return res.status(500).json({ error: 'Internal Server Error' });
      }

      if (results.length > 0) {
        req.session.username = username; // 设置会话变量为用户名
        res.json({ success: true, message: 'Login successful' });
      } else {
        res.json({ success: false, message: 'Invalid username or password' });
      }
    }
  );
});

app.get('/check-session', (req, res) => {
  if (req.session.username) {
    res.json({ loggedIn: true, user: req.session.username });
  } else {
    res.json({ loggedIn: false });
  }
});

app.post('/check-session', (req, res) => {
  console.log(req.session);
  if (req.session.isLoggedIn) {
    res.json({ isLoggedIn: true });
  } else {
    res.json({ isLoggedIn: false });
  }
});

app.post('/logout', (req, res) => {
  req.session.destroy((error) => {
    if (error) {
      console.error('Error destroying session:', error);
      return res.status(500).json({ error: 'Internal Server Error' });
    }

    res.clearCookie('userId'); // 清除会话 cookie
    res.json({ success: true, message: 'Logout successful' });
  });
});

// 启动服务器
app.listen(5000, () => {
  console.log('Server started on port 5000');
});

你在 JSX 文件中尝试使用 <Navigate to="/admin/home" /> 来进行重定向,但这是不正确的做法。重定向应该在组件外部,例如,在路由器组件中完成。根据你的代码,你可以在登录成功后使用路由器的 history 对象来进行重定向,例如:

import { useHistory } from 'react-router-dom';

// ...

const Login = () => {
  const history = useHistory();

  // ...

  const login = (event) => {
    event.preventDefault();

    axios
      .post('http://localhost:5000/login', {
        username: username,
        password: password,
      })
      .then((response) => {
        if (response.data.message) {
          setLoginStatus(response.data.message);
        } else {
          setLoginStatus(response.data.username);
          // 登录成功后进行重定向
          history.push('/admin/home');
        }
      })
      .catch((error) => {
        console.error('Error logging in:', error);
      });
  };

  // ...
};

同样,在检查会话后,你也可以使用 history 对象来进行重定向。这样应该能够正确实现重定向功能。

英文:

I need my user to be redirected upon success. What I have now does not redirect but will present the success pop up message at the end of the form.

JSX File

import React, { useState, useEffect } from &#39;react&#39;;
import axios from &#39;axios&#39;;
import { Navigate } from &#39;react-router-dom&#39;;
const Login = () =&gt; {
const [username, setUsername] = useState(&#39;&#39;);
const [password, setPassword] = useState(&#39;&#39;);
const [loginStatus, setLoginStatus] = useState(&#39;&#39;);
axios.defaults.withCredentials = true;
const login = (event) =&gt; {
event.preventDefault();
axios
.post(&#39;http://localhost:5000/login&#39;, {
username: username,
password: password,
})
.then((response) =&gt; {
if (response.data.message) {
setLoginStatus(response.data.message);
} else {
setLoginStatus(response.data.username);
return &lt;Navigate to=&quot;/admin/home&quot; /&gt;;
}
})
.catch((error) =&gt; {
console.error(&#39;Error logging in:&#39;, error);
});
};
useEffect(() =&gt; {
axios
.get(&#39;http://localhost:5000/check-session&#39;)
.then((response) =&gt; {
if (response.data.loggedIn) {
return &lt;Navigate to=&quot;/admin/home&quot; /&gt;;
// Redirect to /admin/home if already logged in
}
})
.catch((error) =&gt; {
console.error(&#39;Error checking session:&#39;, error);
});
}, []);
return (
&lt;div className=&#39;Login-page&#39;&gt;
&lt;h1&gt;Login&lt;/h1&gt;
&lt;form onSubmit={login}&gt;
&lt;button type=&#39;submit&#39; className=&#39;btn btn-outline-primary&#39;&gt;
Login
&lt;/button&gt;
&lt;/form&gt;
{loginStatus &amp;&amp; &lt;p&gt;{loginStatus}&lt;/p&gt;}
&lt;/div&gt;
);
};
export default Login;

Server.js (Express file)

const express = require(&#39;express&#39;);
const app = express();
const mysql = require(&#39;mysql&#39;);
const morgan = require(&#39;morgan&#39;);
const cors = require(&#39;cors&#39;);
const session = require(&#39;express-session&#39;);
const cookieParser = require(&#39;cookie-parser&#39;);
const bodyParser = require(&#39;body-parser&#39;);
// Middleware
app.use(cors({
origin: &#39;http://localhost:3000&#39;, // Replace with your frontend application&#39;s URL
methods: [&quot;GET&quot;,&quot;POST&quot;,&quot;PUT&quot;, &quot;DELETE&quot;],
credentials: true, // Allow credentials (cookies)
}));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies
app.use(morgan(&#39;dev&#39;)); // Use Morgan for logging HTTP requests
// Session setup
/* Set Cookie Settings */
app.use(
session({
secret: &#39;secretKey123&#39;,
resave: false,
saveUninitialized: false,
cookie: {
secure: false, // Set this to true if you use HTTPS
maxAge: 24 * 60 * 60 * 1000, // 24 hours
},
})
);
// Routes
app.post(&#39;/login&#39;, (req, res) =&gt; {
const username = req.body.username;
const password = req.body.password;
connection.query(
&#39;SELECT * FROM admin_users WHERE username = ? AND password = ?&#39;,
[username, password],
(error, results, fields) =&gt; {
if (error) {
console.error(&#39;Error executing MySQL query: &#39; + error.stack);
return res.status(500).json({ error: &#39;Internal Server Error&#39; });
}
if (results.length &gt; 0) {
req.session.username = username; // Set session variable to the username
res.json({ success: true, message: &#39;Login successful&#39; });
} else {
res.json({ success: false, message: &#39;Invalid username or password&#39; });
}
}
);
});
app.get(&#39;/check-session&#39;, (req, res) =&gt; {
if (req.session.username) {
res.json({ loggedIn: true, user: req.session.username });
} else {
res.json({ loggedIn: false });
}
});
app.post(&#39;/check-session&#39;, (req, res) =&gt; {
console.log(req.session)
if (req.session.isLoggedIn) {
res.json({ isLoggedIn: true });
} else {
res.json({ isLoggedIn: false });
}
});
app.post(&#39;/logout&#39;, (req, res) =&gt; {
req.session.destroy((error) =&gt; {
if (error) {
console.error(&#39;Error destroying session:&#39;, error);
return res.status(500).json({ error: &#39;Internal Server Error&#39; });
}
res.clearCookie(&#39;userId&#39;); // Clear the session cookie
res.json({ success: true, message: &#39;Logout successful&#39; });
});
});
// Start the server
app.listen(5000, () =&gt; {
console.log(&#39;Server started on port 5000&#39;);
});

I have tried using Navigate to redirect but it does nothing. At this point anything would help. Ive tried following a Youtube guide but I ran into an issue with getting the session started. Now I have the session started but it fails to redirect.

答案1

得分: 0

在最新版本的react-router-dom(v6)中,不能像这样导航。

您需要按照以下步骤操作:

从"react-router-dom"中导入{ useNavigate }。

现在在函数中,您必须以以下方式创建它的实例。

const navigate = useNavigate();

现在,您可以使用此导航进行重定向。

只需将您的return <Navigate to="/admin/home" />替换为navigate("/admin/home")

您可以参考此链接获取更多信息:https://reactrouter.com/en/main/hooks/use-navigate

英文:

You can't Navigate like this in the latest version of react-router-dom (v6).

You have to follow these steps:

import { useNavigate } from &quot;react-router-dom&quot;;

Now in the function, you have to create instance of it in the following way.

const navigate = useNavigate();

and, now you can redirect using this navigate.

Just replace your return &lt;Navigate to=&quot;/admin/home&quot; /&gt;
with the navigate(&quot;/admin/home)

You can refer this for more info: https://reactrouter.com/en/main/hooks/use-navigate

答案2

得分: 0

在你的代码中,首先检查 "response.data.message"。

if (response.data.message) {
    setLoginStatus(response.data.message);
}

如果存在消息,你只是设置了登录状态,什么都不做!

在查看后端代码时,无论是有效的用户/密码还是无效的用户/密码,你总是返回一个消息。

if (results.length > 0) {
    req.session.username = username; // 将会话变量设置为用户名
    res.json({ success: true, message: '登录成功' });
} else {
    res.json({ success: false, message: '用户名或密码无效' });
}

这就是为什么它什么都不做。你需要检查一些唯一的东西,例如 "success",并确保没有 "error",然后进行重定向。

英文:

In your code, you're checking first for "response.data.message"

if (response.data.message) {
setLoginStatus(response.data.message);
}

And if there is a message, you just set the login status and do nothing!

When looking to Backend code, you're always returning a message either it is a valid user/password or not.

if (results.length &gt; 0) {
req.session.username = username; // Set session variable to the username
res.json({ success: true, message: &#39;Login successful&#39; });
} else {
res.json({ success: false, message: &#39;Invalid username or password&#39; });
}

This is why it does nothing. You need to check for something unique, "success" for example and also check that there is no "error", then redirect.

答案3

得分: 0

确实如@Maulik所说,你应该使用useNavigatenavigate实例,而不是&lt;Navigate to=&quot;/admin/home&quot; /&gt;

你需要向Axios的post请求添加Content-type头。此外,axios已经有错误处理,因此API的失败响应将直接进入catch块。所以,

const login = (event) =&gt; {
  event.preventDefault();

  axios
    .post(
      &quot;http://localhost:5000/login&quot;,
      {
        username: username,
        password: password,
      },
      {
        headers: { &quot;Content-Type&quot;: &quot;application/json&quot; },
      }
    )
    .then((response) =&gt; {
      setLoginStatus(response.data.username);
      navigate(&quot;/admin/home&quot;, { replace: true });
    })
    .catch((error) =&gt; {
      error?.response
        ? setLoginStatus(error.response.data.message)
        : setLoginStatus(&quot;No server response..&quot;);
    });
};
英文:

It's true what @Maulik said you should use the navigate instance of useNavigate instead of &lt;Navigate to=&quot;/admin/home&quot; /&gt;.

You need to add Content-type header to Axios post. Additionally, axios already has error handling, so failed responses from your API will fall directly into the catch block. So,

const login = (event) =&gt; {
event.preventDefault();
axios
.post(
&quot;http://localhost:5000/login&quot;,
{
username: username,
password: password,
},
{
headers: { &quot;Content-Type&quot;: &quot;application/json&quot; },
}
)
.then((response) =&gt; {
setLoginStatus(response.data.username);
navigate(&quot;/admin/home&quot;, { replace: true });
})
.catch((error) =&gt; {
error?.response
? setLoginStatus(error.response.data.message)
: setLoginStatus(&quot;No server response..&quot;);
});
};

huangapple
  • 本文由 发表于 2023年6月29日 11:44:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577931.html
匿名

发表评论

匿名网友

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

确定