问题描述
我有一个自定义钩子,它将检查您是否已登录,如果尚未登录,则将您重定向到登录页面。这是我的钩子的伪实现,它假定您尚未登录:
import { useRouter } from 'next/router';
export default function useAuthentication() {
if (!AuthenticationStore.isLoggedIn()) {
const router = useRouter();
router.push('/login');
}
}
但是当我使用此钩子时,出现以下错误:
错误:找不到路由器实例。您只应在应用程序客户端内部使用“下一个/路由器”。 https://err.sh/vercel/next.js/no-router-instance
我检查了错误中的链接,但这并没有真正的帮助,因为它只是告诉我将push
语句移至渲染函数。
我也尝试过:
// My functional component
export default function SomeComponent() {
const router = useRouter();
useAuthentication(router);
return <>...</>
}
// My custom hook
export default function useAuthentication(router) {
if (!AuthenticationStore.isLoggedIn()) {
router.push('/login');
}
}
但这只会导致相同的错误。
有什么方法可以允许路由next.js中的React组件之外吗?
解决方法
import Router from 'next/router'
发生错误是因为在页面首次加载的 SSR 期间在服务器上调用了 router.push
。一种可能的解决方法是扩展您的自定义挂钩以在 router.push
的回调中调用 useEffect
,确保该操作仅发生在客户端上。
import { useEffect } from 'react';
import { useRouter } from 'next/router';
export default function useAuthentication() {
const router = useRouter();
useEffect(() => {
if (!AuthenticationStore.isLoggedIn()) {
router.push('/login');
}
},[]);
}
然后在你的组件中使用它:
import useAuthentication from '../hooks/use-authentication' // Replace with your path to the hook
export default function SomeComponent() {
useAuthentication();
return <>...</>;
}
,
创建一个将包装页面组件的HOC
import React,{ useEffect } from "react";
import {useRouter} from 'next/router';
export default function UseAuthentication() {
return () => {
const router = useRouter();
useEffect(() => {
if (!AuthenticationStore.isLoggedIn()) router.push("/login");
},[]);
// yous should also add isLoggedIn in array of dependancy if the value is not a function
return <Component {...arguments} />;
};
}
主要组成部分
function SomeComponent() {
return <>...</>
}
export default UseAuthentication(SomeComponent)