Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 使用react router dom重新加载页面时出现问题_Reactjs_Typescript_Firebase_Routes_React Router Dom - Fatal编程技术网

Reactjs 使用react router dom重新加载页面时出现问题

Reactjs 使用react router dom重新加载页面时出现问题,reactjs,typescript,firebase,routes,react-router-dom,Reactjs,Typescript,Firebase,Routes,React Router Dom,我使用react-router-dom创建了一条专用路由并导航到不同的页面。然而,当我导航到一个页面并重新加载它时,它首先进入/login半秒钟,然后正确地重新加载页面。如何防止这种不必要的行为并改进我的路由 以下是我的路线: <Router> <Route path="/" component={() => !auth ? <Redirect to="/login

我使用
react-router-dom
创建了一条专用路由并导航到不同的页面。然而,当我导航到一个页面并重新加载它时,它首先进入
/login
半秒钟,然后正确地重新加载页面。如何防止这种不必要的行为并改进我的路由

以下是我的路线:

    <Router>
      <Route
        path="/"
        component={() =>
          !auth ? <Redirect to="/login" /> : <Redirect to={path} />
        }
      />
      <Route exact path="/home" component={Home} />
      <Route exact path="/dashboard" component={Dashboard} />
      <Route exact path="/login" component={RedirectPage} />
    </Router>
这是
App
组件:

import {
  Route,
  BrowserRouter as Router,
  Link,
  Redirect,
} from "react-router-dom";
import { Container, Button } from "@material-ui/core/";
import Login from "./Login";
import { useContext,useState } from "react";
import { UserContext } from "../App";
import { signOut } from "../Storage/Auth";

const Routes = () => {
  const { auth, setAuth, logging } = useContext(UserContext);
  const [path,setPath] = useState("/home")
  const handleSignOut = () => {
    signOut(setAuth);
    console.log("Auth", auth);
  };

  const Home = () => {
    console.log("Home");
    return (
      <Container>
        <h1>Welcome</h1>
        <Link to="/">
          <Button onClick={handleSignOut}> Log Out</Button>
        </Link>
        <Link to="/dashboard">
          <Button> Dash</Button>
        </Link>
      </Container>
    );
  };

  const Dashboard = () => {
    setPath("/dashboard")
    console.log("Dash");
    return (
      <Container>
        <Link to="/home">
          <Button> HOME</Button>
        </Link>
        <h1>Dashboard</h1>
      </Container>
    );
  };

  const RedirectPage = () => {
    if (!logging) {
      return <div></div>;
    } else {
      return <Login />;
    }
  };

  return (
    <Router>
      <Route
        path="/"
        component={() =>
          !auth ? <Redirect to="/login" /> : <Redirect to={path} />
        }
      />
      <Route exact path="/home" component={Home} />
      <Route exact path="/dashboard" component={Dashboard} />
      <Route exact path="/login" component={RedirectPage} />
    </Router>
  );
};

export { Routes };

import { useEffect } from "react";
import { Routes } from "./Routing/Routes";
import "./App.css";
import { Container } from "@material-ui/core/";
import initFirebase from "./Storage/Secret";
import { useState, createContext } from "react";
import { onAuthChange } from "./Storage/Auth";

export const UserContext = createContext<any>(null);
function App() {
  const [user, setUser] = useState(null);
  const [auth, setAuth] = useState<string | null>("");
  const [logging, setLogging] = useState(null)
  useEffect(() => {
    initFirebase();
  }, []);

  useEffect(() => {
    onAuthChange(setAuth,setLogging);
  }, [auth]);

  return (
    <UserContext.Provider value={{ user, setUser, auth,setAuth,logging }}>
      <div className="App">
        <Container>
          <Routes />
        </Container>
      </div>
    </UserContext.Provider>
  );
}

export default App;

最后,完整的代码在


如果您有任何建议,我们将不胜感激。

我建议您早点进行身份验证。这样,只有当auth中有内容时,才能渲染路由本身。我认为您的示例也缺少Switch语句,而Switch语句通常很有用


{!啊(
) : (
)}

通常,您希望某种“加载”或“不确定”状态既不表示已验证也不表示未验证。您可以使用第三个“状态”来保持UI,然后再根据身份验证以某种方式呈现

由于
auth
逻辑解析为布尔值
true
|
false

const onAuthChange = (setState, setLoading) => {
  auth().onAuthStateChanged((u) => {
    if (!u) {
      console.log(u);
      setLoading(true);
    } else {
      setState(u);
      setLoading(false);
    }
  });
};
您可以使用这样一个事实,即初始的
auth
状态不是这两种状态。我建议使用
null

const [auth, setAuth] = useState<string | null>(null);
这里请注意,我还切换到了
渲染
属性,
组件
属性用于连接实际的组件。他们的待遇有点不同。您可以阅读有关路由渲染方法差异的信息

完整的路由器示例:

<Router>
  <Switch>
    <Route path="/home" component={Home} />
    <Route path="/dashboard" component={Dashboard} />
    <Route path="/login" component={RedirectPage} />
    <Route
      path="/"
      render={() => {
        if (auth === null) return null;
        return <Redirect to={auth ? path : "/login" />;
      }}
    />
  </Switch>
</Router>

{
if(auth==null)返回null;
返回;
}}
/>

请注意,我还包括了
开关
组件,并对路由进行了重新排序,以便在不太具体的路径之前列出更具体的路径。这允许您从所有路由中删除不必要的
精确的
道具,因为
交换机
以独占方式呈现路由(而不是像
路由器
那样以包含方式呈现路由)。

我终于设法解决了这个问题。现在,重新加载工作正常,安全性也得到了例外的实现。这是我最后的
路由器

<Router>
      <Route
        path="/"
        render={() =>
          logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
        }
      />
      <Route exact path="/" render={() => auth && <Home />} />
      <Route exact path="/dashboard" render={() => auth && <Dashboard />} />
      <Route exact path="/login" component={Login} />
</Router>


日志记录?:
}
/>
验证&&}/>
验证&&}/>
这就是组件现在的样子

import {
  Route,
  BrowserRouter as Router,
  Link,
  Redirect
} from "react-router-dom";
import { Container, Button } from "@material-ui/core/";
import Login from "./Login";
import { useContext, useState, useEffect } from "react";
import { UserContext } from "../App";
import { signOut } from "../Storage/Auth";

const Routes = () => {
  const { auth, setAuth, logging } = useContext(UserContext);
  const handleSignOut = () => {
    signOut(setAuth);
    console.log("Auth", auth);
  };
  const pathname = window.location.pathname;
  const [path, setPath] = useState(pathname);

  useEffect(() => {
    console.log(path);
    path === "/login" && setPath("/");
    path !== "/" && path !== "/dashboard" && setPath("/");
  }, [auth]);

  const Home = () => {
    console.log("Home");
    return (
      <Container>
        <h1>Welcome</h1>
        <Link to="/">
          <Button onClick={handleSignOut}> Log Out</Button>
        </Link>
        <Link to="/dashboard">
          <Button> Dash</Button>
        </Link>
      </Container>
    );
  };

  const Dashboard = () => {
    console.log("Dash");
    return (
      <Container>
        <Link to="/">
          <Button> HOME</Button>
        </Link>
        <h1>Dashboard</h1>
      </Container>
    );
  };

  return (
    <Router>
      <Route
        path="/"
        render={() =>
          logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
        }
      />
      <Route exact path="/" render={() => auth && <Home />} />
      <Route exact path="/dashboard" render={() => auth && <Dashboard />} />
      <Route exact path="/login" component={Login} />
    </Router>
  );
};

export { Routes };
导入{
路线,,
BrowserRouter作为路由器,
链接
重新使用
}从“反应路由器dom”;
从“@material ui/core/”导入{Container,Button}”;
从“/Login”导入登录名;
从“react”导入{useContext,useState,useEffect};
从“./App”导入{UserContext};
从“./Storage/Auth”导入{signOut};
常数路由=()=>{
const{auth,setAuth,logging}=useContext(UserContext);
常量handleSignOut=()=>{
签出(setAuth);
console.log(“Auth”,Auth);
};
const pathname=window.location.pathname;
const[path,setPath]=useState(路径名);
useffect(()=>{
console.log(路径);
路径==“/login”&&setPath(“/”;
路径!=“/”&&path!=“/dashboard”&&setPath(“/”);
},[auth]);
常量Home=()=>{
控制台日志(“主页”);
返回(
欢迎
注销
猛冲
);
};
常量仪表板=()=>{
控制台日志(“破折号”);
返回(
家
仪表板
);
};
返回(
日志记录?:
}
/>
验证&&}/>
验证&&}/>
);
};
出口{路线};

感谢@Richard和@Drew的友好支持。

您能否共享您的私有路由组件,以便我们了解它在解析身份验证状态时的功能,以及您使用私有路由的代码?我怀疑您实际上没有实现
PrivateRoute
组件,尽管从您的代码片段判断。您还可以包括您的
UserContext
代码吗?如果您需要实现身份验证流的帮助,请查看身份验证工作流示例。@drewerese我更新了问题,并将此链接添加到完整的repo中
auth
状态的正常值是多少?您可以从与“已验证”或“未验证”状态不同的初始状态开始,然后等待该值不等于初始状态。@drewrese我添加了验证逻辑。谢谢你的建议。我将试验一下。我正在试验你的建议,以使它发挥作用。非常感谢。
<Router>
  <Switch>
    <Route path="/home" component={Home} />
    <Route path="/dashboard" component={Dashboard} />
    <Route path="/login" component={RedirectPage} />
    <Route
      path="/"
      render={() => {
        if (auth === null) return null;
        return <Redirect to={auth ? path : "/login" />;
      }}
    />
  </Switch>
</Router>
<Router>
      <Route
        path="/"
        render={() =>
          logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
        }
      />
      <Route exact path="/" render={() => auth && <Home />} />
      <Route exact path="/dashboard" render={() => auth && <Dashboard />} />
      <Route exact path="/login" component={Login} />
</Router>

import {
  Route,
  BrowserRouter as Router,
  Link,
  Redirect
} from "react-router-dom";
import { Container, Button } from "@material-ui/core/";
import Login from "./Login";
import { useContext, useState, useEffect } from "react";
import { UserContext } from "../App";
import { signOut } from "../Storage/Auth";

const Routes = () => {
  const { auth, setAuth, logging } = useContext(UserContext);
  const handleSignOut = () => {
    signOut(setAuth);
    console.log("Auth", auth);
  };
  const pathname = window.location.pathname;
  const [path, setPath] = useState(pathname);

  useEffect(() => {
    console.log(path);
    path === "/login" && setPath("/");
    path !== "/" && path !== "/dashboard" && setPath("/");
  }, [auth]);

  const Home = () => {
    console.log("Home");
    return (
      <Container>
        <h1>Welcome</h1>
        <Link to="/">
          <Button onClick={handleSignOut}> Log Out</Button>
        </Link>
        <Link to="/dashboard">
          <Button> Dash</Button>
        </Link>
      </Container>
    );
  };

  const Dashboard = () => {
    console.log("Dash");
    return (
      <Container>
        <Link to="/">
          <Button> HOME</Button>
        </Link>
        <h1>Dashboard</h1>
      </Container>
    );
  };

  return (
    <Router>
      <Route
        path="/"
        render={() =>
          logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
        }
      />
      <Route exact path="/" render={() => auth && <Home />} />
      <Route exact path="/dashboard" render={() => auth && <Dashboard />} />
      <Route exact path="/login" component={Login} />
    </Router>
  );
};

export { Routes };