简体   繁体   English

history.push 到 /login(注销时)在 react-router-dom 中不起作用

[英]history.push to /login (on logout) is not working in react-router-dom

When the users logs in using his/her credentials, the name of the user is displayed on the Header component.当用户使用他/她的凭据登录时,用户的名称会显示在Header组件上。 The user can log out using the logout link.用户可以使用logout链接注销。

在此处输入图像描述

When the user clicks on the logout link, I remove the loggedInUser object saved in local storage.当用户单击logout链接时,我删除了保存在本地存储中的loggedInUser object。 Then, I direct the user to the /login route, where I show the login form to the user.然后,我将用户定向到/login路由,在那里我向用户显示登录表单。

When I use history.push("/login") , and click on the logout link, nothing happens.当我使用history.push("/login")并单击logout链接时,没有任何反应。 The loggedInUser object does not get removed from the local storage, and I am not directed to the login route. loggedInUser object 没有从本地存储中删除,我也没有被定向到login路径。 However, if I use window.location = "/login" , everything works as expected.但是,如果我使用window.location = "/login" ,一切都会按预期工作。

Why is hitory.push("/login") not working as expected?为什么hitory.push("/login")没有按预期工作?

Header.js: Header.js:

import React from "react";
import { Link, withRouter } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { logout } from "./stateSlices/loginSlice";

const Header = ({ history }) => {
  const { loggedInUser } = useSelector((state) => state.login);
  const dispatch = useDispatch();

  const logoutSubmitHandler = () => {
    dispatch(logout());
    localStorage.removeItem("loggedInUser");
    window.location = "/login"; // THIS works
    // history.push("/login"); // THIS does not work
  };

  return (
    <header>
      <nav>
        <ul className="navbar-list">
          {loggedInUser ? (
            <div className="dropdown">
              <button
                className="btn btn-lg btn-primary dropdown-toggle"
                type="button"
                id="dropdownMenu2"
                data-toggle="dropdown"
                aria-haspopup="true"
                aria-expanded="false"
              >
                {loggedInUser.firstName}
              </button>
              <div
                className="dropdown-menu dropdown-menu-right"
                aria-labelledby="dropdownMenu2"
              >
                <button
                  className="dropdown-item"
                  type="button"
                  onClick={logoutSubmitHandler}
                >
                  Logout
                </button>
              </div>
            </div>
          ) : (
            <Link to="/login" className="navbar-list-item">
              Register/Login
            </Link>
          )}
        </ul>
      </nav>
    </header>
  );
};

export default withRouter(Header);

App.js:应用程序.js:

import React from "react";
import Header from "./components/Header";
import { Route, Switch } from "react-router-dom";
import LoginForm from "./components/LoginForm";
import RegisterForm from "./components/RegisterForm";
import Welcome from "./components/Welcome";
import PasswordResetFormEmail from "./components/PasswordResetFormEmail";
import PasswordResetFormPassword from "./components/PasswordResetFormPassword";

const App = () => {
  return (
    <>
      <Header />
      <Switch>
        <Route
          path="/password/reset/:token"
          component={PasswordResetFormPassword}
        />
        <Route
          path="/account/password/forgot"
          component={PasswordResetFormEmail}
        />
        <Route path="/register" component={RegisterForm} />
        <Route path="/login" component={LoginForm} />
        <Route path="/welcome" component={Welcome} />
      </Switch>
    </>
  );
};

export default App;

index.js: index.js:

import React from "react";
import ReactDOM from "react-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from "react-redux";
import store from "./store";

ReactDOM.render(
  <Provider store={store}>
    <Router>
      <App />
    </Router>
  </Provider>,
  document.getElementById("root")
);

You have a typo in your redux slice:您的 redux 切片中有错字:

reducers: {
  logout(state, action) {
    // state.user = null; // <-- Typo error
    state.loggedInUser = null; // This is the correct one
  },
},

But, after fixing the typo, I would recommend that you refactor your code and create a "PrivateRoute" component as demoed in the docs :但是,在修复错字之后,我建议您重构代码并创建一个“PrivateRoute”组件,如文档中演示的那样:

const PrivateRoute = ({ children, ...rest }) => {
  const { loggedInUser } = useSelector((state) => state.login);
  return (
    <Route
      {...rest}
      render={({ location }) =>
        loggedInUser ? (
          children
        ) : (
          <Redirect to={{ pathname: "/login", state: { from: location } }} />
        )
      }
    />
  );
};

and use it in App component for all the private routes:并在App组件中为所有私有路由使用它:

<PrivateRoute path="/welcome">
  <Welcome />
</PrivateRoute>

Now, this way, PrivateRoute will take care of "redirection" to the login page, all you need to do is "clear" the loggedInUser in your redux state.现在,通过这种方式, PrivateRoute将负责“重定向”到登录页面,您需要做的就是“清除” redux state 中的loggedInUser


Note that it is better to use "children" form when defining Routes.请注意,在定义 Routes 时最好使用“children”形式。 See What's the better way to configure routes in App.js in React with react-router-dom?请参阅在 React 中使用 react-router-dom 在 App.js 中配置路由的更好方法是什么?

Try using:尝试使用:

import { useHistory } from "react-router-dom";

const history = useHistory();

const logoutSubmitHandler = () => {
  history.push("/login");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 React Router Dom 中使用 history.push 登录/注销的空白页面 - Blank page on login/logout with history.push in React Router Dom 可以覆盖 React-Router-Dom 的 History.push 方法 - Is possible to override History.push method of React-Router-Dom history.push 使用 react-router-dom - history.push using react-router-dom react-router-dom-链接和history.push之间的区别? - react-router-dom - Difference between link and history.push? history.push(path)在react-router-dom v4中不起作用,在重定向到404时使用redux - history.push(path) is not working in react-router-dom v4, with redux while redirecting to 404 为什么history.push在历史堆栈中产生2个对象,react-router-dom - why history.push produce 2 objects in history stack, react-router-dom 在这种情况下如何使用“history.push”? 反应路由器dom V5 - How Can I Use "history.push" In This Situation? react-router-dom V5 react-router-dom v5 - 链接有效,但 Redirect 和 history.push() 无效 - react-router-dom v5 - Link works, but Redirect and history.push() do not React-router-dom:History.push 连接路径并且不重新路由应用程序 - React-router-dom: History.push concatenates path and doesn't reroute the app 当第二个 history.push 被触发时,react-router-dom 返回 undefined - react-router-dom return undefined when second history.push is triggered
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM