【问题标题】:How do I refactor this into `withAuth` using HOC? Or is it possible to use hooks here in Next.js?如何使用 HOC 将其重构为 `withAuth`?或者是否可以在 Next.js 中使用钩子?
【发布时间】:2021-12-23 21:01:31
【问题描述】:
import { useSession } from 'next-auth/react'

import { LoginPage } from '@/client/components/index'

const Homepage = () => {
  const session = useSession()

  if (session && session.data) {
    return (
      <>
        <div>Homepage</div>
      </>
    )
  }
  return <LoginPage />
}

export default Homepage

基本上,我不想在每一页上写相同的 LoginuseSession() 样板。

我想要类似的东西:

import { withAuth } from '@/client/components/index'

const Homepage = () => {
  return (
    <>
      <div>Homepage</div>
    </>
  )
}

export default withAuth(Homepage)

或者如果可能的话withAuthHook

我目前做了以下事情:

import React from 'react'
import { useSession } from 'next-auth/react'

import { LoginPage } from '@/client/components/index'

export const withAuth = (Component: React.Component) => (props) => {
    const AuthenticatedComponent = () => {
        const session = useSession()
        if (session && session.data) {
            return <Component {...props} />
        }
        return <LoginPage />
    }

    return AuthenticatedComponent
}

但我得到一个错误:

JSX 元素类型“组件”没有任何构造或调用 signatures.ts(2604)

如果我使用React.ComponentType,如下面的答案中所述,我会收到一条错误消息:

TypeError: (0 , client_components_index__WEBPACK_IMPORTED_MODULE_0_.withAuth) 不是函数

【问题讨论】:

    标签: javascript reactjs react-hooks next.js higher-order-components


    【解决方案1】:

    你试过了吗:

    export const withAuth = (Component: React.ComponentType) => (props) => {
    ... 
    

    https://flow.org/en/docs/react/types/#toc-react-componenttype

    编辑: 试试这样:

    export const withAuth = (Component: React.ComponentType) => (props) => {
        const session = useSession()
        if (session && session.data) {
            return <Component {...props} />
        }
        return <LoginPage />
    }
    
    return AuthenticatedComponent
    

    }

    【讨论】:

    • 我觉得我说得太早了。确实有效,但我得到withAuth is not a function error :(
    • @deadcoder0904 我认为这是因为AuthenticatedComponent 被声明为函数组件,但是您从withAuth 返回的已经是一个组件(函数)。您应该返回的只是 JSX,而不是函数 AuthenticatedComponent
    • 哦,现在有道理了!但不知道我该如何从 hoc 中做到这一点?我试着像AuthenticatedComponent() 一样称呼它,但不行。
    • @deadcoder0904 我添加了一些示例代码。
    • 我只这样做了,但它给出了一个错误但不用担心,找到了解决方案。它隐藏在文档中(需要更合适的命名)。我会把它作为答案发布:)
    【解决方案2】:

    答案是hidden in the docs。我必须在_app.tsx 中指定以下Auth 函数:

    import { useEffect } from 'react'
    import { AppProps } from 'next/app'
    import { SessionProvider, signIn, useSession } from 'next-auth/react'
    import { Provider } from 'urql'
    
    import { client } from '@/client/graphql/client'
    
    import '@/client/styles/index.css'
    
    function Auth({ children }: { children: any }) {
        const { data: session, status } = useSession()
        const isUser = !!session?.user
        
        useEffect(() => {
            if (status === 'loading') return
            if (!isUser) signIn()
        }, [isUser, status])
    
        if (isUser) {
            return children
        }
    
        return <div>Loading...</div>
    }
    
    interface AppPropsWithAuth extends AppProps {
        Component: AppProps['Component'] & { auth: boolean }
    }
    
    const CustomApp = ({ Component, pageProps: { session, ...pageProps } }: AppPropsWithAuth) => {
        return (
            <SessionProvider session={session}>
                <Provider value={client}>
                    {Component.auth ? (
                        <Auth>
                            <Component {...pageProps} />
                        </Auth>
                    ) : (
                        <Component {...pageProps} />
                    )}
                </Provider>
            </SessionProvider>
        )
    }
    
    export default CustomApp
    

    在我的实际页面上,我必须将Component.auth 指定为true

    const Homepage = () => {
      return (
        <>
          <div>Homepage</div>
        </>
      )
    }
    
    Homepage.auth = true
    export default Homepage
    

    可以在https://simplernerd.com/next-auth-global-session上找到它的功能的一个很好的总结

    【讨论】:

      猜你喜欢
      • 2019-11-08
      • 2021-06-30
      • 1970-01-01
      • 2021-03-23
      • 2020-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-10
      相关资源
      最近更新 更多