我想<Chats />在用戶通過他們的 gmail ID 登錄后重定向到組件。我還希望uidanduserName作為道具發送到組件,但我無法重定向到該組件。我已經嘗試<Navigate />過承諾,我也嘗試window.location.replace('')過。<Navigate />似乎什么都不做并且window.location.replace('')重定向但道具是空的,我不知道發生了什么,有人可以幫忙嗎?
這是代碼:
import React, {useState} from 'react'
import { signInWithPopup, signOut } from 'firebase/auth'
import { auth, db, provider } from './firebase-config'
import { set, ref, onValue } from 'firebase/database'
import { BrowserRouter as Router, Routes, Route, Navigate} from 'react-router-dom'
import Chats from './components/Chats'
import Homepage from './components/Homepage'
const App = () => {
const [uid, setUid] = useState('')
const [userName, setUserName ] = useState('')
const [redirect, setRedirect] = useState(false)
const signInWithGoogle = () => {
signInWithPopup(auth, provider)
.then(result => {
setUid(result.user.uid)
setUserName(result.user.displayName)
setRedirect(true)
}).catch(err => console.log(err))
}
const signOutWithGoogle = () => {
signOut(auth, provider)
setUserName('')
setRedirect(false)
}
redirect && (<Navigate to='/chats' />)
return (
<Router>
<Routes>
<Route path="/" element={<Homepage signInWithGoogle={signInWithGoogle} signOutWithGoogle={signOutWithGoogle} />} />
<Route path="/chats" element={<Chats uid={uid} name={userName}/>} />
</Routes>
</Router>
)
}
export default App
uj5u.com熱心網友回復:
在 Firebase 中,有一個功能可以幫助您在身份驗證更改時實作一些代碼(即:使用電子郵件登錄后、注冊后、注銷后......),即:
onAuthStateChanged(auth: Auth, nextOrObserver: NextOrObserver<User>, error?: ErrorFn, completed?: CompleteFn): Unsubscribe;
在哪里:
auth: 認證實體nextOrObserver: 身份驗證更改時觸發的回呼error: 錯誤觸發的回呼completed(可選):觀察者被移除時觸發的回呼
您可以在以下位置閱讀更多資訊:https ://firebase.google.com/docs/reference/js/auth.md#onauthstatechanged
基本上,當使用此函式時,您正在訂閱身份驗證觀察者,并且此函式回傳一個取消訂閱函式。因此,這可以完美地useEffect在 React 中使用。看到您的問題后,您可以將這些行放入App組件中:
useEffect(() => {
const unsubscribe = onAuthStateChanged(user => {
// When no user is logged in and the path is '/chats' => redirect to login page
if(user === null && window.location.href.includes('/chats')) {
if(window.location.href.includes('/chats')) return; // This is important, if this line is not presented, the page will reload infinitely
window.location.href = '/'; // Redirect to '/'
}
// After user is logged in => redirect to '/chats'
if(user !== null && window.location.href.includes('/')) {
if(window.location.href.includes('/')) return;
window.location.href = '/chats'; // Redirect to '/chats'
}
});
return unsubcribe; // This must also included
})
在查看您的代碼時,我看到您將所有身份驗證方法和狀態都放在了App組件中。我建議你創建一個包含這些代碼行(以及上面的代碼)的 React 狀態,因為它們應該是全域的。
uj5u.com熱心網友回復:
可以把首頁和聊天放在同一個url路徑下,渲染出符合要求的頁面
<Routes>
<Route path="/" element={uid || userName ? <Chats uid={uid} name={userName}/> :<Homepage signInWithGoogle={signInWithGoogle} signOutWithGoogle={signOutWithGoogle} />} />
</Routes>
或者
<Routes>
{uid || userName ?
<Route path="/chats" element={<Chats uid={uid} name={userName}/>} />
:
<Route path="/" element={<Homepage signInWithGoogle={signInWithGoogle} signOutWithGoogle={signOutWithGoogle} />} />
}
</Routes>
uj5u.com熱心網友回復:
問題
你不能從回呼中回傳 JSX 并期望它被渲染到 DOM 中并做任何事情。
不要使用該window.location方法,因為這會重新加載頁面,從而重新掛載您的應用程式,因此如果沒有將任何 React 狀態持久化到 localStorage 或類似內容,它將丟失。
解決方案 1
使用useNavigate鉤子訪問該navigate函式并使用在路由狀態中發送的適當資料發出命令式重定向。但是,為了讓App組件使用useNavigate鉤子,您需要Router在 ReactTree 中提升它的上方。
例子:
import { Routes, Route, useNavigate } from 'react-router-dom';
const App = () => {
const navigate = useNavigate();
const signInWithGoogle = () => {
signInWithPopup(auth, provider)
.then(result => {
const { displayName, uid } = result.user.uid;
navigate(
"/chats",
{
replace: true,
state: { uid, userName: displayName },
}
);
})
.catch(err => console.log(err));
};
const signOutWithGoogle = () => {
signOut(auth, provider);
setUserName('');
setRedirect(false);
};
return (
<Routes>
<Route path="/" element={<Homepage signInWithGoogle={signInWithGoogle} signOutWithGoogle={signOutWithGoogle} />} />
<Route path="/chats" element={<Chats />} />
</Routes>
);
};
index.js 或App呈現的任何地方
import { BrowserRouter as Router } from 'react-router-dom';
...
<Router>
<App />
</Router>
聊天
使用useLocation鉤子訪問傳遞的路由狀態值。
const { state } = useLocation();
...
const { uid, userName } = state || {};
解決方案 2
如果您不想在路由狀態下發送資料,您可以嘗試使用本地uid和userName狀態并仍然使用該navigate函式強制重定向。你仍然需要提升RouterReactTree。
例子:
const App = () => {
const navigate = useNavigate();
const [uid, setUid] = useState('');
const [userName, setUserName ] = useState('');
const signInWithGoogle = () => {
signInWithPopup(auth, provider)
.then(result => {
setUid(result.user.uid);
setUserName(result.user.displayName);
navigate("/chats", { replace: true });
})
.catch(err => console.log(err));
};
const signOutWithGoogle = () => {
signOut(auth, provider);
setUserName('');
setRedirect(false);
};
return (
<Routes>
<Route path="/" element={<Homepage signInWithGoogle={signInWithGoogle} signOutWithGoogle={signOutWithGoogle} />} />
<Route path="/chats" element={<Chats uid={uid} name={userName}/>} />
</Routes>
)
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/476477.html
