簡體   English   中英

react js用戶在刷新時被重定向到另一個頁面

[英]react js user gets redirected to another page on refresh

我有一個帶有 react-router-dom v6 的 react js 應用程序來處理路由。 在我添加 firebase firestore 之前,路由功能工作得很好,但現在由於某種原因,當我在搜索頁面並重新加載它時,主頁會被渲染。 用戶身份驗證不是問題,因為這是由登錄組件處理的,但我在配置中找不到問題。

這是我的應用程序組件。

import React, {useEffect, useState} from "react";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { createBrowserHistory } from 'history';
import ReactDOM from "react-dom";
import "./styles/style.scss";
import Home from "./pages/home";
import Seeker from "./pages/seeker";
import NotFound from "./pages/notFound";
import Login from "./pages/login";


const App = () => {
    const [token, setToken] = useState(false);

  useEffect(() => {
      if(localStorage.getItem("token") === null){
        setToken(false);
      } else {
        setToken(true);
      }
  }, [])

    return (
        <BrowserRouter history={createBrowserHistory}> 
        <Routes>
            <Route exact path="/" element={<Login isAuth={token}/>}/>
            <Route exact path="/home" element={token ? <Home /> : <Navigate to="/"/>}/> 
            <Route exact path="/seeker" element={token ? <Seeker /> : <Navigate to="/"/>}/> 
            <Route path="*" element={<NotFound />}/>
        </Routes>   
    </BrowserRouter>
) 
}
 

ReactDOM.render(
        <App />,
    document.getElementById("root"))



登錄組件在 localstorage 上正確設置令牌,並且路由使用它來有條件地呈現組件。 但是當我在“/seeker”url 中時,刷新會將我帶到“/home”。

import React, { useState, useEffect } from "react";
import { Formik, Form, Field, ErrorMessage } from 'formik';
import axios from "axios";
require("babel-core/register");
require("babel-polyfill");
import GridRender from "../components/gridRender";
import { NavBar } from "../components/navBar";

async function getHeros(name) {
    return await axios.get(
        `https://www.superheroapi.com/api.php/${name}`
    );
} 

const Seeker = () => {    
    
    const [searchedHero, setSearchedHero] = useState("")
    const [matchedHeros, setMatchedHeros] = useState([]); 


    useEffect(() => {
        let isMounted = true; 
        if (isMounted) {
        getHeros(searchedHero).then((heros) => {
            const hero = heros.data.response != "error" ? heros.data.results : []
            localStorage.setItem("addHeroAction", "true");
            setMatchedHeros(hero);
        }, console.error);
    }
    return () => { isMounted = false };
    }, [searchedHero]);

    return (
        <div>
            <NavBar />
            <div className="seeker">
                <h1 className="title">Find your next teammate!</h1>
                <Formik /> //// here is a large form that i erased so it doesn't get long
                {matchedHeros.length != 0 && <GridRender matchedHeros = {matchedHeros}/>}
            </div>
        </div>
        )
    } 


export default Seeker; 

這是我的 firebase 配置(我使用版本 9)以防萬一,因為在 firebase 實施之后出現了錯誤。

import { initializeApp } from "firebase/app";
import "regenerator-runtime/runtime";
import { addDoc, deleteDoc, doc } from 'firebase/firestore';
import { getFirestore, collection } from 'firebase/firestore'


const firebaseConfig = {
  apiKey: "xxxxxxxxxxxxxxxxxx",
  authDomain: "xxxxxxxxxxxxxxxxxxxx",
  databaseURL: "xxxxxxxxxxxxxxxxxxxxx",
  projectId: "superteam-maker",
  storageBucket: "xxxxxxxxxxxxxxx",
  messagingSenderId: "xxxxxxxxxxxxx",
  appId: "xxxxxxxxxxxxxxxxxxxxxxxxxx"
};

initializeApp(firebaseConfig);
const db = getFirestore();
const colRef = collection(db, "team")


const addHero = (hero) => {
    addDoc(colRef, {
            name : hero.name,
            powerstats :{
                combat: parseInt(hero.powerstats.combat),
                durability: parseInt(hero.powerstats.durability), 
                intelligence: parseInt(hero.powerstats.intelligence),
                power: parseInt(hero.powerstats.power),
                speed: parseInt(hero.powerstats.speed),
                strength : parseInt(hero.powerstats.strength)
            },
            id: parseInt(hero.id),
            image: {url : hero.image.url},
            
    } )
}

const deleteHero = (hero) => {
    const docRef = doc(db, "team", hero.id);
    deleteDoc(docRef);
}


export {addHero, deleteHero, colRef}

////////更新/////////

登錄組件使用返回隨機令牌的測試 API 對用戶進行身份驗證,因此用戶只有在提交某個 email 和密碼后才能進入。 如果身份驗證成功,用戶將被呈現到“/home”。

這是登錄組件的代碼。

import React, {useEffect, useState} from "react";
import { Formik } from 'formik';
import { Navigate } from 'react-router-dom';
import axios from "axios";


const Login = (props) => {
  const [token, setToken] = useState(false);

  useEffect(() => {
      if(localStorage.getItem("token") === null){
        setToken(false);
      } else {
        setToken(true);
      }
  }, []) 


  const verification = () => {
    if( token && props.isAuth){
      return <Navigate to="/home"/>
    }
  }

    let logInError = {};
    return(
      <div className="login__background">
        <div className="login container">
          {verification()}
          <h1 className="display-1 title login__title">Make a team as <span>powerfull</span> as you!</h1>
          <h5 className="login-title__sub">Please log in to create your superteam</h5>
            <Formik
            initialValues={{ email: '', password: '' }}
            validate={values => {
            const errors = {};
            
            if (!values.email) {
              errors.email = 'Required';
            } else if (
              !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
            ) {
              errors.email = 'Invalid email address';
            } 
            
            if (!values.password){
                errors.password = "Required";
            } 
            return errors;
            }}
            onSubmit={(values) => {
                axios.post("http://challenge-react.alkemy.org/", values)
                .then(response => {
                    let token = response.data.token
                    localStorage.setItem("token", token);
                    localStorage.setItem("addHeroAction", false);
                    setToken(true);
                    return <Navigate to="/home"/>
                })
                .catch(error => {
                    if (error.response) {
                        logInError = error.response.data.error;
                        window.alert(logInError);
                      } else if (error.request) {
                        console.log(error.request);
                      } else {
                        console.log('Error', error.message);
                      }
                      console.log(error.config);
                })
            }}>

            {({
              values,
              errors,
              touched,
              handleChange,
              handleBlur,
              handleSubmit
            }) => (
            <form onSubmit={handleSubmit}>
                <label className="form-label label" name="email">Email</label>
                <br />
              <input
                className="form-control form-control-lg input"
                type="email"
                name="email"
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.email}
              />
              {errors.email && touched.email && errors.email}
              <br />
              <label className="form-label label " name="password">Password</label>
              <br />
              <input
                className="form-control form-control-lg input"
                type="password"
                name="password"
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.password}
              />
              {errors.password && touched.password && errors.password}
              <br />
              <button type="submit" className="btn btn-danger">
                Submit
              </button>
            </form>
            )}
            </Formik>
            
        </div>
      </div>
    )

}

export default Login;

它還會從 App.js 獲取 IsAuth 屬性,以防這是用戶第一次進入頁面並且沒有保存令牌。

我看到的問題是token state 最初是錯誤的。 useEffect在渲染周期結束時運行,因此初始渲染token為 false

const [token, setToken] = useState(false);

useEffect(() => {
  if (localStorage.getItem("token") === null) {
    setToken(false);
  } else {
    setToken(true);
  }
}, []);

並且使用token state 呈現的任何Route都將使用此初始false值並采取相應措施。

<Route path="/seeker" element={token ? <Seeker /> : <Navigate to="/" />} /> 

如果在"/seeker"路徑上並且token值為false ,則呈現Navigate組件。

假設您的所有身份驗證流程都正確且有效,並將token值設置為 localStorage,那么您應該localStorage 初始化token state。

const initializeState = () => !!JSON.parse(localStorage.getItem("token"));

const [token, setToken] = useState(initializeState);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM