英文:
lost auth state when page refresh in reactjs hooks
问题
以下是您要翻译的代码部分:
当我使用有效的凭据登录时,服务器会将JWT发送到浏览器,我将这个JWT存储在本地存储中,页面重定向到主页,一切正常。在主页上,我有一个`loadUser`函数,它发送请求到服务器以获取有效用户的用户详细信息。但是当我刷新页面时,主页永远不会执行,因为认证状态返回为false,页面从主页重定向到登录页面。
这是App.js
import React, { Fragment } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Navbar from "./components/layout/Navbar";
import Home from "./components/pages/Home";
import Login from "./components/auth/Login";
import PrivateRoute from "./components/routing/PrivateRoute";
import "./App.css";
const App = () => {
return (
<AuthState>
<Router>
<Fragment>
<Navbar />
<div className="container">
<Alerts />
<Switch>
<PrivateRoute exact path="/" component={Home} />
<Route exact path="/login" component={Login} />
</Switch>
</div>
</Fragment>
</Router>
</AuthState>
);
};
export default App;
这是我的authState
代码,成功登录后状态会从这里更改:
import React, { useReducer } from "react";
import axios from "axios";
import AuthContext from "./authContext";
import authReducer from "./authReducer";
import {
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "../types";
const AuthState = (props) => {
const initialState = {
isAuthenticated: null,
user: null,
};
const [state, dispatch] = useReducer(authReducer, initialState);
// Load User
const loadUser = async () => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get("/api/auth");
dispatch({ type: USER_LOADED, payload: res.data });
} catch (err) {
dispatch({ type: AUTH_ERROR });
}
};
// Login User
const login = async (formData) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
try {
const res = await axios.post("api/auth", formData, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
loadUser();
} catch (err) {
dispatch({
type: LOGIN_FAIL,
payload: err.response.data.msg,
});
}
};
return (
<AuthContext.Provider
value={{
isAuthenticated: state.isAuthenticated,
user: state.user,
loadUser,
login,
}}
>
{props.children}
</AuthContext.Provider>
);
};
export default AuthState;
这是authReducer.js
的减速器代码:
import {
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "../types";
export default (state, action) => {
switch (action.type) {
case USER_LOADED:
return {
...state,
isAuthenticated: true,
user: action.payload,
};
case LOGIN_SUCCESS:
localStorage.setItem("token", action.payload.token);
return {
...state,
isAuthenticated: true,
};
case AUTH_ERROR:
case LOGIN_FAIL:
localStorage.removeItem("token");
return {
...state,
isAuthenticated: false,
user: null,
};
default:
return state;
}
};
这是私有路由:
import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import AuthContext from "../../context/auth/authContext";
const PrivateRoute = ({ component: Component, ...rest }) => {
const authContext = useContext(AuthContext);
const { isAuthenticated, loading } = authContext;
return (
<Route
{...rest}
render={(props) =>
!isAuthenticated && !loading ? (
<Redirect to="/login" />
) : (
<Component {...props} />
)
}
/>
);
};
export default PrivateRoute;
请注意,我已经将您提供的代码部分进行了翻译,如有需要,请随时提出更多问题。
英文:
When i login with valid credentials server send JWT to browser i store this JWT in localstore page redirect to home page everything works fine and in home page i have loadUser function which send request to server to get the user details of valid user but when i refresh the page it home page never execute because auth state returns to false and page redirect from home to login page
This is App.js
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
import React, { Fragment } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Navbar from "./components/layout/Navbar";
import Home from "./components/pages/Home";
import Login from "./components/auth/Login";
import PrivateRoute from "./components/routing/PrivateRoute";
import "./App.css";
const App = () => {
return (
<AuthState>
<Router>
<Fragment>
<Navbar />
<div className="container">
<Alerts />
<Switch>
<PrivateRoute exact path="/" component={Home} />
<Route exact path="/login" component={Login} />
</Switch>
</div>
</Fragment>
</Router>
</AuthState>
);
};
export default App;
<!-- end snippet -->
This is my authsate code from where my state changes after successful login
import React, { useReducer } from "react";
import axios from "axios";
import AuthContext from "./authContext";
import authReducer from "./authReducer";
import {
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "../types";
const AuthState = props => {
const initialState = {
isAuthenticated: null,
user: null,
};
const [state, dispatch] = useReducer(authReducer, initialState);
// Load User
const loadUser = async () => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get("/api/auth");
dispatch({ type: USER_LOADED, payload: res.data });
} catch (err) {
dispatch({ type: AUTH_ERROR });
}
};
// Login User
const login = async formData => {
const config = {
headers: {
"Content-Type": "application/json"
}
};
try {
const res = await axios.post("api/auth", formData, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
loadUser();
} catch (err) {
dispatch({
type: LOGIN_FAIL,
payload: err.response.data.msg
});
}
};
return (
<AuthContext.Provider
value={{
isAuthenticated: state.isAuthenticated,
user: state.user,
loadUser,
login,
}}
>
{props.children}
</AuthContext.Provider>
);
};
export default AuthState;
This is reducer code authReducer.js
import {
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "../types";
export default (state, action) => {
switch (action.type) {
case USER_LOADED:
return {
...state,
isAuthenticated: true,
user: action.payload
};
case LOGIN_SUCCESS:
localStorage.setItem("token", action.payload.token);
return {
...state,
isAuthenticated: true
};
case AUTH_ERROR:
case LOGIN_FAIL:
localStorage.removeItem("token");
return {
...state,
isAuthenticated: false,
user: null,
};
default:
return state;
}
};
This is private route
import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import AuthContext from "../../context/auth/authContext";
const PrivateRoute = ({ component: Component, ...rest }) => {
const authContext = useContext(AuthContext);
const { isAuthenticated, loading } = authContext;
return (
<Route
{...rest}
render={props =>
!isAuthenticated && !loading ? (
<Redirect to="/login" />
) : (
<Component {...props} />
)
}
/>
);
};
export default PrivateRoute;
答案1
得分: 1
可能是用于用户认证/授权的JSON Web令牌。您能否提供更多关于此的信息?
英文:
Probably the JSON web token which is used for user authentication/authorization. Can you give us more information about this?
答案2
得分: 1
这是可以预料的。
如果您想要持久保存令牌,应将其保存在 localStorage
或 cookie
中。
然后,您应该在 componentDidMount
中或在使用 hooks
时在 useEffect
中(带有空依赖数组)检查令牌的存在和有效性。
如果您能告诉我们您在哪里发出 AJAX
请求,那将很好,例如,如果您正在使用 Axios
,您可以在请求拦截器中封装这个逻辑。
英文:
That's to be expected.
If you want to persist the token you should save it in localStorage
or a cookie
.
Then, you should check for the token existence and validity in componentDidMount
or in an useEffect
(with a void dependency array) if you are using hooks
.
It'd be nice if you could show us where you are making AJAX
requests because if, for example, you are using Axios
you can encapsulate this logic in a request
interceptor.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论