[英]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.