简体   繁体   English

React-Router-Dom 无法渲染页面,但由于 PrivateRoute 而路由返回

[英]React-Router-Dom unable to render page but routes back due to PrivateRoute

I am having some issues with my routing currently when authenticated.我目前在通过身份验证时遇到了一些路由问题。 Whenever I try to access my ViewPortfolio page at localhost:3000/portfolio/ portfolioId it will redirect me back to my homepage.每当我尝试在 localhost:3000/portfolio/ portfolioId访问我的 ViewPortfolio 页面时,它都会将我重定向回我的主页。 I am not sure what is going on.我不确定发生了什么。 I have also tried manipulating the URL by modifying it to the correct URL link but it also redirects me back to /homepage when I am authenticated.我还尝试通过将 URL 链接修改为正确的 URL 链接来操作 URL,但它也会在我通过身份验证时将我重定向回/homepage The source codes can be found below.源代码可以在下面找到。 App.js is my router with PrivateRoute as the private route component and finally, CreateInterview.js where I redirect using js windows.location function to ViewPortfolio.js which will use useParams() react hook to get the param. App.js 是我的路由器,其中 PrivateRoute 作为私有路由组件,最后是 CreateInterview.js,我使用 js windows.location function 重定向到 ViewPortfolio.js,它将使用useParams() react hook 来获取参数。 But instead now after creating successfully and redirect to the correct URL with the portfolioId it will redirect back to homepage within less than a second.但是现在,在成功创建并重定向到正确的 URL 后,它会在不到一秒的时间内重定向回主页。

PrivateRoute.js PrivateRoute.js

import React from 'react' 
import { Route, Redirect } from 'react-router-dom' 
import { useAuth } from '../contexts/AuthContext' 
 
const PrivateRoute = ({ component: Component, ...rest }) => { 
  const { currentUser } = useAuth() 
 
  return ( 
    <Route 
      {...rest} 
      render={(props) => { 
        if (currentUser) { 
          return <Component {...props} /> 
        } else { 
          return <Redirect to={{ 
            pathname: "/", 
            state:{ 
              from: props.location 
            } 
          }}/> 
        } 
      } 
      }> 
 
    </Route> 
  ) 
} 
 
export default PrivateRoute

App.js应用程序.js

import React from "react" 
.
.
.
import PublicRoute from "./PublicRoute"; 
 
function App() { 
    return ( 
        <AuthProvider> 
            <Router> 
                <Switch> 
                    {/* Auth Routes */} 
                    <PublicRoute exact path='/' component={Login} /> 
                    .
                    .
                    .
                    <PrivateRoute exact path='/createInterview' component={CreateInterview} /> 
                    <PrivateRoute path='/manageInterview' component={ManageInterview} /> 
                    <PrivateRoute path='/portfolio/:portfolioId' component={ViewPortfolio} /> 
 
                    {/* Non-Existance Routes */} 
                    <Route path="*" component={() => "404 NOT FOUND"} /> 
                </Switch> 
            </Router> 
        </AuthProvider> 
    ) 
} 
 
export default App

CreatInterview.js redirecting in js (onSubmit of the form) CreatInterview.js 在 js 中重定向(表单的 onSubmit)

async function handleSubmit(e) { 
    e.preventDefault(); 
    setError(''); 
    setLoading(true); 
 
    await database.portfolioRef.add({ 
      intervieweeName: intervieweeNameRef.current.value, 
      intervieweeEmail: intervieweeEmailRef.current.value, 
      intervieweeMobileNumber: intervieweeMobileRef.current.value, 
      projectTitle: projectTitleRef.current.value, 
      portfolioTitle: portfolioNameRef.current.value, 
      dateCreated: new Date().toLocaleString('en-SG'), 
      createdBy: currentUser.displayName 
    }).then(function(docRef) { 
      console.log("This is the Document ID " + docRef.id.toString()); 
      console.log(docRef.id); 
      window.location = '/portfolio/' + docRef.id; 
    }) 
 
    setLoading(false) 
  }

Part of ViewPortfolio.js to receive the portfolioId from CreateInterview.js ViewPortfolio.js 的一部分,用于从 CreateInterview.js 接收portfolioId

const ViewPortfolio = () => { 
    let { portfolioId } = useParams(); 

AuthContext.js AuthContext.js

import React, { useContext, useState, useEffect } from "react" 
import { auth, database } from "../firebase"; 
import { getDocs, query, where } from "firebase/firestore"; 
 
const AuthContext = React.createContext() 
 
export function useAuth() { 
    return useContext(AuthContext) 
} 
 
export function AuthProvider({ children }) { 
    const [currentUser, setCurrentUser] = useState(null) 
    const [loading, setLoading] = useState(true) 
 
    function login(email, password) { 
        return auth.signInWithEmailAndPassword(email, password).then(() => { 
            const Doc = query(database.usersRef, where("email", "==", email)); 
 
            getDocs(Doc).then((querySnapshot) => { 
                let values = ''; 
 
                querySnapshot.forEach((doc) => { 
                    values = doc.id; 
                }); 
 
                var userUpdate = database.usersRef.doc(values); 
                userUpdate.update({ 
                    lastActive: new Date().toLocaleString('en-SG'), 
                }) 
            }) 
        }); 
    } 
 
    function logout() { 
        return auth.signOut(); 
    } 
 
    function forgetPassword(email) { 
        return auth.sendPasswordResetEmail(email); 
    } 
 
    function updateEmail(email) { 
        return currentUser.updateEmail(email) 
    } 
 
    function updatePassword(password) { 
        return currentUser.updatePassword(password) 
    } 
 
    function updateDisplayName(name) { 
        return currentUser.updateDisplayName(name) 
    } 
 
    useEffect(() => { 
        const unsubscribe = auth.onAuthStateChanged( user => { 
            setLoading(false) 
            setCurrentUser(user) 
        }) 
 
        return unsubscribe 
    }, []) 
 
    const value = { 
        currentUser, 
        login, 
        forgetPassword, 
        logout, 
        updateEmail, 
        updatePassword, 
        updateDisplayName, 
    } 
 
    return ( 
        <AuthContext.Provider value={value}> 
            {!loading && children} 
        </AuthContext.Provider> 
    ) 
}

The initial currentUser state matches the unauthenticated state, so when the app initially renders, if you are accessing a protected route the redirection will occur because the currentUser state hasn't updated yet.初始currentUser状态与未经身份验证的状态匹配,因此当应用程序最初呈现时,如果您正在访问受保护的路由,则会发生重定向,因为currentUser状态尚未更新。

Since onAuthStateChanged returns null for unauthenticated users then I suggest using anything other than null for the initial currentUser state.由于onAuthStateChanged为未经身份验证的用户返回null ,因此我建议对初始currentUser状态使用null以外的任何内容。 undefined is a good indeterminant value. undefined是一个很好的不确定值。 You can use this indeterminant value to conditionally render a loading indicator, or nothing at all, while the auth status is confirmed on the initial render.您可以使用此不确定值有条件地渲染加载指示器,或者根本不渲染任何内容,同时在初始渲染时确认身份验证状态。

AuthProvider身份验证提供者

export function AuthProvider({ children }) { 
  const [currentUser, setCurrentUser] = useState(); // <-- undefined
  ...

PrivateRoute私人路由

const PrivateRoute = (props) => { 
  const { currentUser } = useAuth();

  if (currentUser === undefined) {
    return null; // or loading spinner, etc...
  }

  return currentUser
    ? (
      <Route {...props} />
    )
    : (
      <Redirect
        to={{ 
          pathname: "/", 
          state: { 
            from: props.location 
          } 
        }}
      />
    );
}

You should also really replace the window.location = '/portfolio/' + docRef.id;您还应该真正替换window.location = '/portfolio/' + docRef.id; logic with a history.push('/portfolio/' + docRef.id);带有history.push('/portfolio/' + docRef.id); so you are not unnecessarily reloading the page.所以你不会不必要地重新加载页面。

const history = useHistory();

...

async function handleSubmit(e) { 
  e.preventDefault(); 
  setError(''); 
  setLoading(true); 

  try {
    const docRef = await database.portfolioRef.add({ 
      intervieweeName: intervieweeNameRef.current.value, 
      intervieweeEmail: intervieweeEmailRef.current.value, 
      intervieweeMobileNumber: intervieweeMobileRef.current.value, 
      projectTitle: projectTitleRef.current.value, 
      portfolioTitle: portfolioNameRef.current.value, 
      dateCreated: new Date().toLocaleString('en-SG'), 
      createdBy: currentUser.displayName 
    });
     
    history.push('/portfolio/' + docRef.id);
  } catch (error) {
    // handle error, clear loading state
    setLoading(false);
  }
}

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

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