Node.js Axios请求不使用React+;重演
我将尝试给出一个前提,然后用代码跟进它 我决定在我的React项目中实现MaterialUI,并且大部分工作都在进行中。如何设置应用程序,用户将面临登录页面。Login.js模块呈现,输入他们的凭据,然后单击submit。Node.js Axios请求不使用React+;重演,node.js,reactjs,redux,react-redux,Node.js,Reactjs,Redux,React Redux,我将尝试给出一个前提,然后用代码跟进它 我决定在我的React项目中实现MaterialUI,并且大部分工作都在进行中。如何设置应用程序,用户将面临登录页面。Login.js模块呈现,输入他们的凭据,然后单击submit。formData、onChange和onSubmit作为道具从登录组件传递给登录组件,登录组件通过MapStateTrops接收这些道具。登录组件使用connect中间件将redux状态链接到react应用程序 单击submit会触发formData(在传递给SignIn组件的
formData
、onChange
和onSubmit
作为道具从登录组件传递给登录组件,登录组件通过MapStateTrops
接收这些道具。登录组件使用connect中间件将redux状态链接到react应用程序
单击submit会触发formData(在传递给SignIn组件的登录组件中)点击位于“../../actions/auth”中的myLogin
方法代码>。错误发生在这个方法中,在try-catch中的axios调用中,我试图与后端通信const-response=wait-axios.post(“/api/auth”,body,config)代码>
奇怪的是dispatch({type:LOGIN\u SUCCESS,payload:response.data})
从不被命中,它应该将状态设置为从后端返回的令牌,因为似乎从未执行LOGIN\u SUCCESS
。但是非常奇怪的是,控制台记录令牌实际上是有效的!似乎它从未被存储,而是强制调用AUTH_ERROR
这是我的登录组件:
// Login.js
import SignIn from "../../material/SignIn";
const Login = ({ setAlert, login, isAuthenticated }) => {
const [formData, setFormData] = useState({
email: "",
password: ""
});
const { email, password } = formData;
const onChange = e => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const onSubmit = e => {
login(email, password);
};
// Redirect if logged in
if (isAuthenticated) {
return <Redirect to="/dashboard" />;
}
return (
<Fragment>
<SignIn
email={email}
password={password}
onSubmit={onSubmit}
onChange={onChange}
isAuthenticated={isAuthenticated}
/>
</Fragment>
);
};
Login.propTypes = {
setAlert: PropTypes.func.isRequired,
login: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(
mapStateToProps,
{ setAlert, login }
)(Login);
// Login user
export const login = (email, password) => async dispatch => {
// Config needed because we're sending data
const config = {
headers: {
"Content-Type": "application/json"
}
};
const body = JSON.stringify({ email, password });
try {
const response = await axios.post("/api/auth", body, config);
// Skips over this dispatch
dispatch({
type: LOGIN_SUCCESS,
payload: response.data
});
// But hits this dispatch.. and then console logs 'REACHED' as seen below
dispatch(loadUser());
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach(error => {
dispatch(setAlert(error.msg, "danger"));
});
}
dispatch({
type: LOGIN_FAIL
});
}
};
如果您注意到,在axios调用之后,loadUser被调用
,定义为:
// Load user
export const loadUser = () => async dispatch => {
const token = localStorage.token;
console.log('REACHED!'); // reached
if (token) {
setAuthToken(token);
}
try {
const response = await axios.get("/api/auth");
dispatch({
type: USER_LOADED,
payload: response.data
});
} catch (err) {
dispatch({
type: AUTH_ERROR // This is dispatched
});
}
};
后端路由如下所示:
// @route POST api/auth
// @desc Authenticate user and get token
// @access Public
router.post(
"/",
[
check("email", "Please include a valid email").isEmail(),
check("password", "Please is required").exists()
],
async (req, res) => {
const errors = validationResult(req);
// send back any errors
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
const { email, password } = req.body;
try {
// check if user exists, send error if so
let user = await User.findOne({ email });
if (!user) {
return res
.status(400)
.json({ errors: [{ msg: "Invalid credentials" }] });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res
.status(400)
.json({ errors: [{ msg: "Invalid credentials" }] });
}
// return jsonwebtoken so that way they're logged in right
// away, without having to log in after registering
const payload = {
user: {
id: user.id
}
};
jwt.sign(
payload,
config.get("jwtSecret"),
{
expiresIn: process.env.PORT ? 3600 : 36000
},
(err, token) => {
if (err) throw err;
console.log(token); // prints token!
return res.json({ token });
}
);
} catch (err) {
console.log(err);
res.status(500).send("Server error");
}
}
);
在这一点上我很困惑。正在呈现令牌,但React似乎没有在节点有机会将其发送回之前“等待”响应。不知道如何解释这一点,但我通过从表单标记中去掉onSubmit触发器并将其放置在in SignIn.js上解决了这一问题。我将按钮的类型也更改为类型按钮。让它工作:)不知道如何解释,但我解决了这个问题,从表单标签中去掉了onSubmit触发器,并将其放在in-SignIn.js中。我将按钮的类型也更改为类型按钮。让它工作起来:)您使用的是什么中间件?它需要支持异步操作。您说过“错误发生…”,但不清楚错误发生的位置和原因。这是AJAX请求中的错误吗?还是JS例外?“记录代币实际有效”您在哪里尝试记录代币?@EricHasselbring在我决定尝试实现Material UI之前,一切都很好。@ThiagoBarcala在我在问题中发布的最后一个函数中,在JWT.sign的POST api/auth
中。似乎令牌是在后端创建的,但在前端的const response=wait..
中没有返回您使用的中间件是什么?它需要支持异步操作。您说过“错误发生…”,但不清楚错误发生的位置和原因。这是AJAX请求中的错误吗?还是JS例外?“记录代币实际有效”您在哪里尝试记录代币?@EricHasselbring在我决定尝试实现Material UI之前,一切都很好。@ThiagoBarcala在我在问题中发布的最后一个函数中,在JWT.sign的POST api/auth
中。似乎令牌是在后端创建的,但不会在前端的const response=wait..
中返回
// @route POST api/auth
// @desc Authenticate user and get token
// @access Public
router.post(
"/",
[
check("email", "Please include a valid email").isEmail(),
check("password", "Please is required").exists()
],
async (req, res) => {
const errors = validationResult(req);
// send back any errors
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
const { email, password } = req.body;
try {
// check if user exists, send error if so
let user = await User.findOne({ email });
if (!user) {
return res
.status(400)
.json({ errors: [{ msg: "Invalid credentials" }] });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res
.status(400)
.json({ errors: [{ msg: "Invalid credentials" }] });
}
// return jsonwebtoken so that way they're logged in right
// away, without having to log in after registering
const payload = {
user: {
id: user.id
}
};
jwt.sign(
payload,
config.get("jwtSecret"),
{
expiresIn: process.env.PORT ? 3600 : 36000
},
(err, token) => {
if (err) throw err;
console.log(token); // prints token!
return res.json({ token });
}
);
} catch (err) {
console.log(err);
res.status(500).send("Server error");
}
}
);