reactjs - React-redux 在 header 组件更新后无限发送 dispatch 请求
问题描述
我是redux的新手。成功登录后,标头会重新呈现,但随后会无限分派USER_LOADED
. 我将 mapToProps 从通用导入更改为特定导入,但仍然无法解决此问题。我发现一篇文章提到了从 app.js 中取消链接标头,但我没有得到它。就像不知道该怎么做一样。
应用程序.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;
页眉.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);
登录.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,
errors: [],
};
case dux.REGISTER_SUCCESS:
case dux.LOGIN_SUCCESS:
return {
...state,
...payload,
isAuthenticated: true,
loading: false,
errors: [],
};
case dux.REGISTER_FAIL:
case dux.LOGIN_FAIL:
return {
...state,
token: null,
isAuthenticated: false,
loading: false,
user: null,
errors: payload,
};
case dux.AUTH_ERROR:
case dux.LOGOUT:
return {
...state,
token: null,
user: null,
isAuthenticated: false,
loading: false,
errors: [],
};
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,
payload: res.data,
});
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,
payload: res.data,
});
dispatch(loadUser());
history.push("/userList");
} catch (err) {
console.log(err);
dispatch({
type: action.REGISTER_FAIL,
payload: err.response.data.errors,
});
}
};
export const logout = () => async (dispatch) =>
dispatch({ type: action.LOGOUT });
解决方案
在 loadUser 中,我递归地调用它。这导致了这个问题。但在这些时间里,我了解到最好从 redux 商店传递特定项目以提高性能。谢谢你们的快速反应。
推荐阅读
- node.js - EJS 和条件语句
- libreoffice - 在行中查找最后填充的条目
- c - 回调函数与 C 中的 void 表达式有问题?
- angular - 当我单击子组件的输入时,会显示一个 div,我怎样才能一次制作一个或隐藏其他?
- c# - C# .NetCore HttpClient PostAsync Multipart Form-Data,带有文件附件和进度,供 PowerShell 使用
- apache-spark - 在 kubernetes 上运行 Spark 时出现错误“java.lang.UnsatisfiedLinkError:__strncpy_chk”
- kubernetes - Docker Desktop for Windows kubelet 日志位于何处?
- mysql - 在 SQL 中以分钟为步长在时间间隔之间生成时间序列
- python - 计算给定文本文件中每个单词的出现次数
- context-free-grammar - 显示语法。S->aS|aSbS|Ɛ 有歧义并找到明确的语法