Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/451.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
Javascript ReactJs,Typescript保护路由,以HOC作为功能组件_Javascript_Reactjs_Next.js - Fatal编程技术网

Javascript ReactJs,Typescript保护路由,以HOC作为功能组件

Javascript ReactJs,Typescript保护路由,以HOC作为功能组件,javascript,reactjs,next.js,Javascript,Reactjs,Next.js,我不知道如何构建一个简单的HOC来保护组件,也就是说,在组件呈现之前,确保用户已登录 下面是我构建HOC以保护组件的尝试(目前还不起作用) 导出默认函数ProtectedRoute(组件:React.ComponentType){ return()=>{ const authUser=useSession(); const router=useRouter(); 如果(窗口类型===‘未定义’){ 返回null; } 如果(!authUser){ router.push('/login'); 返

我不知道如何构建一个简单的HOC来保护组件,也就是说,在组件呈现之前,确保用户已登录

下面是我构建HOC以保护组件的尝试(目前还不起作用)

导出默认函数ProtectedRoute(组件:React.ComponentType){
return()=>{
const authUser=useSession();
const router=useRouter();
如果(窗口类型===‘未定义’){
返回null;
}
如果(!authUser){
router.push('/login');
返回null;
}
返回;
};
}
这是我想要保护的组件

const AppLayout=({
儿童
标题='这是默认标题',
}:道具):React.ReactElement=>{
返回(
...
{儿童}
)
}
导出默认的ProtectedRoute(AppLayout);
这是我如何调用布局组件的:

函数应用程序({Component,pageProps}:any){
返回(
) 
}
导出默认应用程序;
这是我的错误消息:
类型为“({children,title,}:Props)=>React.ReactElement”的参数不能分配给类型为“ComponentType”的参数。类型“({children,title,}:Props)=>React.ReactElement”不可分配给类型“FunctionComponent”。参数“\u0”和“props”的类型不兼容。类型“{children?:ReactNode;}”中缺少属性“title”,但类型“Props”中需要属性“title”


您有什么提示吗?

简而言之,您的
AppLayout
不会返回
ReactElement
,而是返回
FC
(功能组件)

我建议这种类型的差异


下面是一个可以找到的工作示例项目

组件/AppContext/index.tsx

import { createContext, useCallback, useContext, useState } from "react";
import type { FC, ReactNode } from "react";

type Context = {
  isAuthenticated: Boolean;
  handleAuthentication: () => void;
}

const AppContext = createContext<Context>({
  isAuthenticated: false,
  handleAuthentication: () => {},
});

const AppContextProvider: FC<{ children: ReactNode }> = ({ children }) => {
  const [isAuthenticated, setAuthentication] = useState(false);

  const handleAuthentication = useCallback(() => {
    setAuthentication((prevState) => !prevState);
  }, []);

  return (
    <AppContext.Provider
      value={{
        isAuthenticated,
        handleAuthentication,
      }}
    >
      {children}
      {isAuthenticated && (
        <button type="button" onClick={handleAuthentication}>
          Log out
        </button>
      )}
    </AppContext.Provider>
  );
};

export const useAppContext = () => useContext(AppContext);

export default AppContextProvider;
import { useRouter } from "next/router";
import { useEffect } from "react";
import { useAppContext } from "../AppContext";
import type { FC } from "react";

type withAuthenticationFn = (Component: FC) => FC;

const withAuthentication: withAuthenticationFn = (Component) => {
  const Authenticated: FC = (): JSX.Element | null => {
    const { isAuthenticated } = useAppContext();
    const router = useRouter();

    useEffect(() => {
      if (!isAuthenticated) router.push("/login");
    });

    return isAuthenticated ? <Component /> : null;
  };

  return Authenticated;
};

export default withAuthentication;
import AppContextProvider from "../components/AppContext";
import type { FC } from "react";
import type { AppProps } from "next/app";

const App: FC<AppProps> = ({ Component, pageProps }) => (
  <AppContextProvider>
    <Component {...pageProps} />
  </AppContextProvider>
);

export default App;
import Head from "next/head";
import Link from "next/link";
import withAuthentication from "../components/withAuthentication";
import type { NextPage } from "next";

const AboutPage: NextPage = () => (
  <>
    <Head>
      <title> About - Next App</title>
    </Head>
    <h1>About</h1>
    <p>This is the about page</p>
    <p>
      <Link href="/">
        <a>Go home</a>
      </Link>
    </p>
  </>
);

export default withAuthentication(AboutPage);
从“react”导入{createContext,useCallback,useContext,useState};
从“react”导入类型{FC,ReactNode};
类型上下文={
未验证:布尔值;
手工验证:()=>无效;
}
const AppContext=createContext({
I认证:错误,
handleAuthentication:()=>{},
});
常量AppContextProvider:FC=({children})=>{
const[isAuthenticated,setAuthentication]=useState(false);
const handleAuthentication=useCallback(()=>{
setAuthentication((prevState)=>!prevState);
}, []);
返回(

); 使用身份验证导出默认值(约页);
页面/索引.tsx

import { createContext, useCallback, useContext, useState } from "react";
import type { FC, ReactNode } from "react";

type Context = {
  isAuthenticated: Boolean;
  handleAuthentication: () => void;
}

const AppContext = createContext<Context>({
  isAuthenticated: false,
  handleAuthentication: () => {},
});

const AppContextProvider: FC<{ children: ReactNode }> = ({ children }) => {
  const [isAuthenticated, setAuthentication] = useState(false);

  const handleAuthentication = useCallback(() => {
    setAuthentication((prevState) => !prevState);
  }, []);

  return (
    <AppContext.Provider
      value={{
        isAuthenticated,
        handleAuthentication,
      }}
    >
      {children}
      {isAuthenticated && (
        <button type="button" onClick={handleAuthentication}>
          Log out
        </button>
      )}
    </AppContext.Provider>
  );
};

export const useAppContext = () => useContext(AppContext);

export default AppContextProvider;
import { useRouter } from "next/router";
import { useEffect } from "react";
import { useAppContext } from "../AppContext";
import type { FC } from "react";

type withAuthenticationFn = (Component: FC) => FC;

const withAuthentication: withAuthenticationFn = (Component) => {
  const Authenticated: FC = (): JSX.Element | null => {
    const { isAuthenticated } = useAppContext();
    const router = useRouter();

    useEffect(() => {
      if (!isAuthenticated) router.push("/login");
    });

    return isAuthenticated ? <Component /> : null;
  };

  return Authenticated;
};

export default withAuthentication;
import AppContextProvider from "../components/AppContext";
import type { FC } from "react";
import type { AppProps } from "next/app";

const App: FC<AppProps> = ({ Component, pageProps }) => (
  <AppContextProvider>
    <Component {...pageProps} />
  </AppContextProvider>
);

export default App;
import Head from "next/head";
import Link from "next/link";
import withAuthentication from "../components/withAuthentication";
import type { NextPage } from "next";

const AboutPage: NextPage = () => (
  <>
    <Head>
      <title> About - Next App</title>
    </Head>
    <h1>About</h1>
    <p>This is the about page</p>
    <p>
      <Link href="/">
        <a>Go home</a>
      </Link>
    </p>
  </>
);

export default withAuthentication(AboutPage);
从“下一个/链接”导入链接;
从“下一个/Head”导入Head;
从“./components/withAuthentication”导入withAuthentication;
从“下一步”导入类型{NextPage};
常量索引扩展:下一页=()=>(
仪表板-下一个应用程序
你好,Next.js