1

试图将 DefaultLayout 组件设置为初始状态值。它抛出无法解构未定义的属性子项。

如果我将 DefaultLayout 组件包装在 React.memo 中,它可以正常工作,即导出默认 React.memo(DefaultLayout)

任何人都可以解释这种行为的原因。

请找到沙盒链接

https://codesandbox.io/s/autumn-firefly-qp5gh?file=/pages/index.js

布局.js

import React, { useEffect, useState } from 'react'
import { AppLayout } from 'utilities/appComponentConfig'
import { useGlobalUI } from 'store/GlobalUI'
import { APP_TYPE } from 'utilities/Constants'
import { fetchKioskInfo } from '../services/kiosk'

const Layout = ({ Pages, pageProps, cookie }) => {
  const { setAppType, setAgentCookie } = useGlobalUI()
  const [Component, setComponent] = useState(AppLayout[APP_TYPE.WEB])
  setAgentCookie(cookie)
  useEffect(() => {
    const fetchKiosk = async () => {
      const kioskDetails = await fetchKioskInfo(cookie)
      if (kioskDetails?.length > 0) {
        setAppType(APP_TYPE.KIOSK)
        return setComponent(AppLayout[APP_TYPE.KIOSK])
      } else {
        setAppType(APP_TYPE.WEB)
        return setComponent(AppLayout[APP_TYPE.WEB])
      }
    }

    if(cookie?.includes('KIOSK'))fetchKiosk()
  }, [])

  return (
    <>
      {Component ? (
        <Component pageProps={pageProps}>
          <Pages {...pageProps} />
        </Component>
      ) : null}
    </>
  )
}

export default Layout

appComponentConfig.js

import { APP_TYPE } from './Constants'

import DefaultLayout from 'layouts/DefaultLayout'
import KioskLayout from 'layouts/KioskLayout'

const AppLayout = {
  [APP_TYPE.WEB]: DefaultLayout,
  [APP_TYPE.KIOSK]: KioskLayout,
}

export { AppLayout }

DefaultLayout.js

const DefaultLayout = ({ children, pageProps }) => {
  const mainNode = pageProps.main || {}
  const settings = mainNode.settings || {}
  const showFooter = !settings.hideFooter
  const errorDetail = _find(pageProps, (item) => item.error && item.status)
  const router = useRouter()

  return (
    <>
        <div style={{ display: 'none' }} className="version">
          Version 1.0.5
        </div>
      </div>
    </>
  )
}

export default DefaultLayout

_app.js

import React, { useEffect } from 'react'
import { useCookie } from 'next-cookie'
import '../styles/main.css'
import UserProvider from '../store/User'
import PageProvider from '../store/Page'
import GlobalUIProvider from '../store/GlobalUI'
import BookingProvider from '../store/Booking'
import ExtraProvider from '../store/Extras'
import CartProvider from '../store/Cart'
import CheckoutProvider from '../store/Checkout'
import { useRouter } from 'next/router'
import { storePathValues } from '../utilities/helperFunctions'
import Layout from 'layouts/Layout'

const App = ({ Component: Pages, pageProps, cookie }) => {
  const router = useRouter()

  return (
    <>
      <PageProvider model={pageProps}>
        <GlobalUIProvider>
          <UserProvider>
            <CartProvider>
              <CheckoutProvider>
                <BookingProvider>
                  <ExtraProvider>
                    <Layout
                      Pages={Pages}
                      pageProps={pageProps}
                      cookie={agentCookie}
                    />
                  </ExtraProvider>
                </BookingProvider>
              </CheckoutProvider>
            </CartProvider>
          </UserProvider>
        </GlobalUIProvider>
      </PageProvider>
    </>
  )
}

export default App
4

1 回答 1

0

可能是因为它React.memo是一个高阶组件,即它以一个 React 组件作为参数并返回一个装饰的 React 组件。也许它与处理导出的顺序有关,并且使用memoHOC 对此进行了调整。

无论哪种方式,我认为将 React 组件存储在 state 中有点反模式。我建议存储当前的“活动”APP_TYPE值,并在渲染该Layout组件时派生要渲染的组件。

const Layout = ({ Pages, pageProps, cookie }) => {
  const { setAppType, setAgentCookie } = useGlobalUI();

  const [componentType, setComponentType] = useState(APP_TYPE.WEB);

  setAgentCookie(cookie);

  useEffect(() => {
    const fetchKiosk = async () => {
      const kioskDetails = await fetchKioskInfo(cookie);
      const type = kioskDetails?.length ? APP_TYPE.KIOSK : APP_TYPE.WEB;

      setAppType(type);
      setComponentType(type);
    }

    if (cookie?.includes('KIOSK')) {
     fetchKiosk();
    }
  }, []);

  const Component = AppLayout[componentType];

  return (
    <>
      {Component && (
        <Component pageProps={pageProps}>
          <Pages {...pageProps} />
        </Component>
      )}
    </>
  )
}
于 2021-12-02T06:43:08.153 回答