问题描述
我是 redux 的新手。成功登录后,标头会重新呈现,但会无限调度 USER_LOADED
。我将 mapToProps 从通用更改为特定导入,但仍然无法解决此问题。我发现一篇文章提到从 app.js 取消链接头,但我没有得到它。就像不知道该怎么做一样。
App.js
const App = () => {
useEffect(() => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
store.dispatch(loadUser());
window.addEventListener("storage",() => {
if (!localStorage.token) store.dispatch({ type: logoUT });
});
},[]);
return (
<Provider store={store}>
<Router>
<Header />
<ToastContainer />
<Switch>
<Route exact path="/" component={Landing} />
<Route exact path="/login" component={Login} />
{/* <Route exact path="/register" component={Register} /> */}
<Route exact path="/userList" component={UserList} />
</Switch>
</Router>
</Provider>
);
};
export default App;
Header.js
const Header = ({ user,logout }) => {
const [current,setCurrent] = useState("home");
const handleClick = (e) => setCurrent(e.key);
//const { user } = auth;
return (
<Menu onClick={handleClick} selectedKeys={[current]} mode="horizontal">
<Item key="home" icon={<HomeOutlined />}>
<Link to="/"> Training</Link>
</Item>
{!user && (
<Item key="register" icon={<UserAddOutlined />} className="float-right">
<Link to="/register">Register</Link>
</Item>
)}
{!user && (
<Item key="login" icon={<UserOutlined />} className="float-right">
<Link to="/login">Login</Link>
</Item>
)}
{user && (
<SubMenu
key="SubMenu"
icon={<Loginoutlined />}
title={(user.name && user.name) || (user.email && user.email)}
className="float-right"
>
<Item icon={<logoutOutlined />} onClick={logout}>
logout
</Item>
</SubMenu>
)}
</Menu>
);
};
Header.propTypes = {
user: PropTypes.object,};
const mapStatetoProps = (state) => ({
user: state.auth.user,});
export default connect(mapStatetoProps,{ logout })(Header);
Login.js
const Login = ({ loading,errors,login,history }) => {
const [email,setEmail] = useState("");
const [password,setPassword] = useState("");
const getin = async (e) => {
e.preventDefault();
if (!email.trim() || !password.trim()) {
toast.error("Both email and password are required");
return;
}
login({ email,password },history);
};
return (
<div className="search-params">
<form onSubmit={getin}>
<label htmlFor="email">email</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<label htmlFor="password">Password</label>
<input
type="password"
id="password"
value={password}
placeholder="minimum 6 characters"
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit" disabled={!email || !password || loading}>
Submit
</button>
</form>
{errors &&
errors.map((error,index) => (
<p key={index} className="text-danger">
{error.msg}
</p>
))}
</div>
);
};
Login.propTypes = {
email: PropTypes.string,user: PropTypes.object,password: PropTypes.string,};
const mapStatetoProps = (state) => ({
loading: state.auth.loading,isAuthenticated: state.auth.isAuthenticated,errors: state.auth.errors,});
export default connect(mapStatetoProps,{ login })(Login);
减速器
const initialState = {
token: localStorage.getItem("token"),isAuthenticated: null,loading: true,user: null,errors: [],};
const auth = (state = initialState,action) => {
const { type,payload } = action;
switch (type) {
case dux.USER_LOADED:
return {
...state,user: payload,isAuthenticated: true,loading: false,};
case dux.REGISTER_SUCCESS:
case dux.LOGIN_SUCCESS:
return {
...state,...payload,};
case dux.REGISTER_FAIL:
case dux.LOGIN_FAIL:
return {
...state,token: null,isAuthenticated: false,errors: payload,};
case dux.AUTH_ERROR:
case dux.logoUT:
return {
...state,};
default:
return state;
}
};
export default auth;
actionCreators.js
import api from "../../utils/api";
import * as action from "./actionTypes";
export const loadUser = () => async (dispatch) => {
try {
const res = await api.get("/auth");
dispatch({
type: action.USER_LOADED,payload: res.data,});
dispatch(loadUser());
} catch (err) {
dispatch({
type: action.AUTH_ERROR,});
}
};
//Login user
export const login = (formData,history) => async (dispatch) => {
try {
const res = await api.post("/auth",formData);
console.log("res in login action",res);
dispatch({
type: action.LOGIN_SUCCESS,});
dispatch(loadUser());
history.push("/userList");
} catch (err) {
console.log(err);
dispatch({
type: action.LOGIN_FAIL,payload: err.response.data.errors,});
}
};
//Register User
export const register = (formData,history) => async (dispatch) => {
try {
const res = await api.post("/users",formData);
dispatch({
type: action.REGISTER_SUCCESS,});
dispatch(loadUser());
history.push("/userList");
} catch (err) {
console.log(err);
dispatch({
type: action.REGISTER_FAIL,});
}
};
export const logout = () => async (dispatch) =>
dispatch({ type: action.logoUT });
解决方法
在 loadUser 中,我递归调用它。这导致了这个问题。但是在这几个小时里,我了解到从 redux store 传递特定项目以提高性能总是更好。感谢您的快速回复。