这是我的身份验证上下文
import { createContext } from "react";
const AuthContext = createContext();
export default AuthContext;
这是我的身份验证缩减器
import { AUTH_ERROR, LOGIN_SUCCESS } from "../types";
export default (state, action) => {
switch (action.type) {
case LOGIN_SUCCESS:
localStorage.setItem("token", action.payload.data.token);
return {
...state,
isAuthenticated: true,
userName: action.payload.data.name,
avatar: action.payload.data.avatar,
token: action.payload.data.token,
error: null,
};
case AUTH_ERROR:
localStorage.removeItem("token");
return {
...state,
isAuthenticated: false,
userName: null,
avatar: null,
error: action.payload.message,
};
default:
return state;
}
};
这是我的身份验证状态
import React, { useReducer } from "react";
import axios from "axios";
import AuthContext from "./AuthContext";
import AuthReducer from "./AuthReducer";
import { AUTH_ERROR, LOGIN_SUCCESS } from "../types";
const AuthState = ({ children }) => {
const initialState = {
isAuthenticated: false,
userName: null,
avatar: null,
token: null,
error: null,
};
const [state, dispatch] = useReducer(AuthReducer, initialState);
const login = async (formData) => {
const header = {
headers: {
"Content-Type": "application/json",
},
};
try {
const res = await axios.post("/api/tenant/auth/login", formData, header);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
} catch (err) {
dispatch({
type: AUTH_ERROR,
payload: err.response.data,
});
}
};
return (
<AuthContext.Provider
value={{
token: state.token,
isAuthenticated: state.isAuthenticated,
userName: state.userName,
avatar: state.avatar,
error: state.error,
login,
}}
>
{children}
</AuthContext.Provider>
);
};
export default AuthState;
在我的应用程序中.js我已经像这样包裹了组件;
function App() {
return (
<AuthState>
<AlertState>
<SettingsState>
<Alert />
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/login" exact component={Login} />
<Route path="/dashboard" exact component={Dashboard} />
<Route path="/main-settings" exact component={MainSettings} />
</Switch>
</Router>
</SettingsState>
</AlertState>
</AuthState>
);
}
然后在我的登录组件中,我尝试像这样使用来自身份验证上下文提供程序的数据;
const Login = ({ history }) => {
const { login, error, userName, isAuthenticated } = useContext(AuthContext);
const { setAlert } = useContext(AlertContext);
return (
<Formik
initialValues={{ email: "", password: "" }}
validationSchema={Yup.object({
email: Yup.string().email("Invalid email address").required("Required"),
password: Yup.string().required("Required"),
})}
onSubmit={async (values, { resetForm, setSubmitting }) => {
const { email, password } = values;
await login({
email,
password,
});
console.log(error, userName, isAuthenticated);
}}
>
{(formik) => (
<>
<div className="container">
<div className="row justify-content-center">
<div className="col-md-8 col-lg-6 col-xl-5">
<div className="card mt-5 shadow">
<div className="card-body p-4" id="error-body">
<div className="text-center mb-4">
<h4 className="text-uppercase mt-0">Sign In</h4>
</div>
<form id="login-form" onSubmit={formik.handleSubmit}>
<div className="form-group">
<label htmlFor="email" className="float-left">
Email <span className="text-danger">*</span>
</label>
<input
type="text"
className="form-control"
id="email"
placeholder=""
name="email"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.email}
/>
{formik.touched.email && formik.errors.email ? (
<div className="text-danger">
{formik.errors.email}
</div>
) : null}
</div>
<div className="form-group">
<label htmlFor="password" className="float-left">
Password <span className="text-danger">*</span>
</label>
<input
type="password"
className="form-control"
id="password"
placeholder="Password"
name="password"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.password}
/>
{formik.touched.password && formik.errors.password ? (
<div className="text-danger">
{formik.errors.password}
</div>
) : null}
</div>
<div className="form-group">
<button
className="btn btn-primary btn-block"
type="submit"
style={{
backgroundColor: "#007bff",
borderColor: "#007bff",
}}
>
Log In
</button>
</div>
<hr />
<div className="form-group mb-3 d-flex justify-content-between">
<div className="custom-control custom-checkbox">
<input
type="checkbox"
className="custom-control-input"
id="rememberMe"
value="remember"
/>
<label
className="custom-control-label"
htmlFor="rememberMe"
>
Remember Me
</label>
</div>
<h6>Forgot Password?</h6>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</>
)}
</Formik>
);
};
提交后,我签入开发人员工具,看到上下文提供程序已更新,但每当我使用 useContext 访问数据时,我都会从控制台获取状态的初始数据。我认为在发出初始请求并更新状态后,我的组件在某个地方没有被重新渲染。因此,在后续请求中,即当我获得更新的值时。我做错了什么,因此,我如何在第一个请求时获得更新的值?
尝试将console.log(error, userName, isAuthenticated);
从 onSubmit 函数中移出并将其放在以下行下:const { setAlert } = useContext(AlertContext);
,您现在看到更新的上下文值了吗?