繁体   English   中英

this.props.history.push() 正在更改 URL 但不执行下一页的操作

[英]this.props.history.push() is changing the URL but not doing the action to the next page

我正在使用 react-router v6。 在登录页面的身份验证 function (singIn) 中,我调用了 history.push。 URL 发生变化,但不执行移动到正确页面的操作,而是保留在登录页面中。 身份验证正在工作,如果我单击 URL 并按“Enter”,身份验证后,页面仍然会推送。

我的 Index.jsx (根)

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import RoutesController from './routes';

ReactDOM.render(

  <React.StrictMode>
    <RoutesController />
  </React.StrictMode>,

  document.getElementById('root')
);

我的 routes.js(路由控制器):

import React from 'react';
import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom'
import HomePage from './App/pages/HomePage'
import UsersPage from './App/pages/UsersPage'
import Login from './App/pages/Login'
import PrivateRoute from './Auth'
import { createBrowserHistory } from "history";


const customHistory = createBrowserHistory();



function RoutesController() {   
    
    return (
        <Router>
            <Routes>
                <Route path="/" element={<Login history={customHistory}/>} />

                <Route path="/home" element={<PrivateRoute />}>
                    <Route path="" element={<HomePage />} />
                </Route>

                <Route path="/users" element={<PrivateRoute />}>
                    <Route path="" element={<UsersPage />} />
                </Route>

                <Route path="*" element={<h1>NOT FOUND</h1>} />

            </Routes>
        </Router>
    )

}

export default RoutesController

我的登录.jsx:

import React, { Component } from "react";
import Wrapper from "../../../components/Wrapper";
import "./style.css"
import logo from "../../../assets/icons/logotipo_semfundo.png"
import Button from "@material-ui/core/Button";
import { MdEmail, MdLock } from "react-icons/md"


class Login extends Component {

    constructor(props) {
        super(props)
        this.state = {
            message: '',
        }
    }       

    signIn = () => {

        const data = { email: this.email, password: this.password }

        const requestInfo = {
            method: 'POST',
            body: JSON.stringify(data),
            headers: new Headers({
                'Content-Type': 'application/json'
            }),
        }

        fetch('http://localhost:3000/api/login', requestInfo).then(response => {
            if (response.ok) {
                return response.json()
            }
            throw new Error('Login Inválido...')
        }).then(token => {
            localStorage.setItem('accessToken', token)            
            this.props.history.push({pathname: "/home", message: "Ok"})
            return        
            
        }
        ).catch(e => (this.setState({ message: e.message })))
    }

    render() {
        
        localStorage.removeItem('accessToken')
        return (
            <Wrapper className="login">
                <Wrapper className="login-img">
                    <img src={logo} alt="logo" />
                </Wrapper>

                <Wrapper className="login-form">
                    <h1 className="h1" >Login</h1>
                    {
                        this.state.message !== '' ? (
                            <span color="black">{this.state.message}</span>
                        ) : ''
                    }
                    <form id="loginForm">
                        <Wrapper>
                            <Wrapper>
                                <MdEmail />
                                <input
                                    id="email"
                                    type="text"
                                    name="email"
                                    placeholder="Digite um E-mail"
                                    onChange={e => this.email = e.target.value}
                                ></input>
                            </Wrapper>
                            <Wrapper>
                                <MdLock />
                                <input
                                    id="password"
                                    type="password"
                                    name="password"
                                    placeholder="Senha"
                                    onChange={e => this.password = e.target.value}
                                ></input>
                            </Wrapper>
                            <Wrapper>
                                <Button
                                    // label="Submit"
                                    // type="submit"
                                    // form="loginForm"
                                    onClick={() => this.signIn()}
                                    color="primary"
                                >
                                    Entrar
                                </Button>
                            </Wrapper>
                        </Wrapper>
                    </form>
                </Wrapper>
            </Wrapper>
        )

    }
}



export default Login

认证页面:

import React from 'react'
import { Navigate, Outlet } from 'react-router-dom'

const isAuth = () => {    
    if (localStorage.getItem('accessToken') !== null) {  
        return true
    } 
    return false 
}

const PrivateRoute = () => {
    return (
        isAuth() ? <Outlet />
            : <Navigate
                to={{
                    pathname: '/',
                    state: { message: 'Usuário não autorizado' }
                }}
            />
    )
}

export default PrivateRoute 

问题

react-router-dom v6 中,更高级别的路由器组件维护自己的内部history引用,因此通过在RoutesController中创建自己的历史记录并将其传递给Login组件,它不会使用与路由器相同的历史记录 object。

除此之外,RRDv6 也不再公开history object 而是公开navigate function以用于命令式导航。 换句话说,而不是history.push("/newpath")它被简单地替换为navigate("/newpath")

另一个问题是Navigate组件没有使用 object 作为to属性。 state现在是一级道具。

解决方案

您有几个选项或它们的组合可以从Login组件访问导航,但最简单和更直接的是将Login转换为 React function 组件并使用useNavigate挂钩来访问导航。

import { useNavigate } from 'react-router-dom';

const Login = () => {
  const navigate = useNavigate(); // <-- call hook to get navigate function

  const [message, setMessage] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');

  const signIn = () => {
    const data = { email, password };

    const requestInfo = {
      method: 'POST',
      body: JSON.stringify(data),
      headers: new Headers({
        'Content-Type': 'application/json'
      }),
    };

    fetch('http://localhost:3000/api/login', requestInfo)
      .then(response => {
        if (response.ok) {
          return response.json();
        }
        throw new Error('Login Inválido...');
      })
      .then(token => {
        localStorage.setItem('accessToken', token);
        navigate("/home", { state: { message: "Ok" } }); // <-- navigate to new path
      })
      .catch(e => {
        localStorage.removeItem('accessToken');
        setMessage(e.message);
      });
    }
  }
    
  return (
    <Wrapper className="login">
      <Wrapper className="login-img">
        <img src={logo} alt="logo" />
      </Wrapper>

      <Wrapper className="login-form">
        <h1 className="h1">Login</h1>
        {message && <span color="black">{message}</span>}
        <form id="loginForm">
          <Wrapper>
            <Wrapper>
              <MdEmail />
              <input
                id="email"
                type="text"
                name="email"
                placeholder="Digite um E-mail"
                onChange={e => setEmail(e.target.value)}
              />
            </Wrapper>
            <Wrapper>
              <MdLock />
              <input
                id="password"
                type="password"
                name="password"
                placeholder="Senha"
                onChange={e => setPassword(e.target.value)}
              />
            </Wrapper>
          <Wrapper>
          <Button
            // label="Submit"
            // type="submit"
            // form="loginForm"
            onClick={signIn}
            color="primary"
          >
            Entrar
          </Button>
        </form>
      </Wrapper>
    </Wrapper>
  );
};

对于PrivateRoute组件,将 state 作为顶级道具。

<Navigate
  to='/'
  state={{ message: 'Usuário não autorizado' }}
/>

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM