該賞金過期2天。此問題的答案有資格獲得 100聲望獎勵。 Ruudy想引起更多人對這個問題的關注。
useSession((s) => s.user)將回傳用戶object或null. 在索引頁面上應該顯示用戶的姓名。PrivatePageProvider如果用戶物件為空,則頁面被包裝在其中將重定向客戶端。因此,如果用戶為空,IndexPage則甚至不應呈現,而是提供程式回傳空并重定向。然而,這是不作業和TypeError被拋出,因為IndexPage試圖訪問name的null。使用 react-router 這種方法有效,但不適用于 Next。我知道我可以只使用可選的鏈接運算子,但我想假設user如果頁面包含在PrivatePageProvider.
function PrivatePageProvider({ children }) {
const user = useSession((s) => s.user);
const router = useRouter();
useEffect(() => {
if (!user) {
router.push('/auth/login');
}
}, [user, router]);
return !user ? null : children;
}
function IndexPage() {
const user = useSession((s) => s.user);
return (
<PrivatePageProvider>
<h1>Hello {user.name}</h1>
</PrivatePageProvider>
);
}
錯誤:
TypeError: Cannot read properties of null (reading 'name')
為什么即使IndexPage未呈現此錯誤也會顯示?如何在不涉及服務器端的情況下使我的方法起作用?
uj5u.com熱心網友回復:
為什么即使未呈現 IndexPage 也會顯示此錯誤?> 因為它壞了,你有一個錯誤,它不會渲染。
如何在不涉及服務器端的情況下使我的方法起作用?> 將您的代碼包裝在useEffect. useEffect只會執行客戶端,因此任何在服務器端呈現的內容都會忽略效果并等待它在執行之前呈現。那是因為任何效果都只會在 DOM 被渲染后執行。如果user在服務器上為空,它將中斷,user.name除非您將其移動到效果。
此外,我對您到底要做什么感到很困惑,為什么useEffect在子組件中根本沒有 a ,而您應該在IndexPage. 我也不確定PrivatePageProvider它的用途是什么,如果頁面提供者正在呈現索引頁面會更有意義,反之亦然。您也不應該將用戶作為孩子傳遞,而是傳遞資料道具并在子頁面中呈現用戶,然后您就不需要再次獲取用戶。
話雖如此,看著您的代碼,在我看來,您好像在嘗試做某事,然后在途中因不小心將您的想法與您使用頁面和頁面提供程式的方式交換而感到困惑/迷失。也許這就是你想要的:
const PrivatePageProvider = ({children}) => {
const user = useSession((s) => s.user)
const router = useRouter()
useEffect(() => {
if (!user) {
router.push('/auth/login')
}
}, [user])
return !user ? <></> : children
}
const IndexPage = () => {
const user = useSession((s) => s.user)
return <h1>Hello {user.name}</h1>
}
這樣你就可以像這樣使用它:
<PrivatePageProvider>
<IndexPage/>
</PrivatePageProvider>
<PrivatePageProvider>
<ExamplePage/>
</PrivatePageProvider>
uj5u.com熱心網友回復:
我認為這種方法也不適用于 react-router。錯誤是關于 javascript 在執行代碼時知道的背景關系。為了更好地理解,您渲染的 JSX 樹被轉換為普通 js 如下所示:
function IndexPage() {
const user = useSession((s) => s.user);
return (React.createElement(PrivatePageProvider, null,
React.createElement("h1", null,
"Hello ",
user.name)));
}
當 javascript 執行一個函式時,它首先評估引數;在這種情況下,當它看到其中一個試圖訪問 null object( user.name)上的屬性時,它甚至不呼叫函式就拋出 TypeError。
如果您將整個用戶物件作為道具傳遞給另一個元素,情況就不同了
function IndexPage() {
const user = useSession((s) => s.user);
return (
<PrivatePageProvider>
<SomeComponent user={user} />
</PrivatePageProvider>
);
}
它轉譯為
function IndexPage() {
const user = useSession((s) => s.user);
return (React.createElement(PrivatePageProvider, null,
React.createElement(SomeComponent, { user: user })));
}
這里javascript不知道您將訪問user.name內部SomeComponent,因此它會繼續執行而不會出錯
我建議使用 Context API 為包裝在您的組件中的組件提供非空用戶 PrivatePageProvider
const UserContext = React.createContext({});
const useUser = () => {
const { user } = useContext(UserContext);
return user;
};
function PrivatePageProvider({ children }: any) {
const user = useSession((s) => s.user);
...
return !user ? null : (
<UserContext.Provider value={{ user }}>{children}</UserContext.Provider>
);
}
function SomeComponent() {
const user = useUser();
return <h1>{user.name}</h1>;
}
function IndexPage() {
return (
<PrivatePageProvider>
<SomeComponent />
</PrivatePageProvider>
);
}
uj5u.com熱心網友回復:
我的專案也有類似的問題。我曾經nextJS跟next-auth那個next-auth提供loading狀態。我不知道如何獲取用戶資料,但loading除了user使用loading. 像這樣 :
function PrivatePageProvider({ children }) {
const [session, loading] = useSession();
const router = useRouter();
const isAuthenticate = !!user;
useEffect(() => {
if (loading) return; // Do nothing while loading
if (!isAuthenticate) {
router.push('/auth/login'); // If not authenticated, force log in
}
}, [user, loading]);
if(isAuthenticate) {
return <>children</>
}
// Session is being fetched, or no user.
// If no user, useEffect() will redirect.
return <span>... loading</span>;
}
next-auth如果你喜歡使用它,我把包地址放上:
next-auth
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/357643.html
