簡體   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