英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论