【问题标题】:unable to fetch data in nextjs headless WordPress无法在 nextjs 无头 WordPress 中获取数据
【发布时间】:2021-08-16 09:54:30
【问题描述】:

这是我的标题组件 --

import { isEmpty } from "lodash";
import Nav from "./Nav";

const Header = ({ headerMenus }) => {
  // console.log(headerMenus); <- Here i get the menus
  if (isEmpty(headerMenus)) {
    return null;
  }
  return (
    <Header>
      <Nav headerMenus = {headerMenus}/>
    </Header>
  );
};
export default Header;

当我通过道具向导航发送数据时,我在导航组件中没有得到任何数据,请帮助 这里是 Nav 的代码

const Nav = ({headerMenus}) =>{
  // console.log(headerMenus); <~~ Not getting data here so i can't return anything through this 

  return;
};
export default Nav;

【问题讨论】:

    标签: wordpress next.js react-props headless-cms


    【解决方案1】:

    您是否使用 WPGraphQL 作为您的端点?你也很可能需要一个不记名令牌,除非你的端点可以被公开自省。我会从我当前的无头 wordpress 版本中发布一些文件

    首先,考虑使用类似 apollo 客户端的东西来提供全局一致的缓存。 SWR 和 GraphQL Query 也很棒。

    dynamic-nav.graphql

    # import DynamicNavFragment from '../Partials/dynamic-nav-fields.graphql'
    
    query DynamicNav(
        $idHead: ID!
        $idTypeHead: WordpressMenuNodeIdTypeEnum!
        $idFoot: ID!
        $idTypeFoot: WordpressMenuNodeIdTypeEnum!
    ) {
        Header: wordpress {
            menu(id: $idHead, idType: $idTypeHead) {
                menuItems(where: { parentId: 0 }) {
                    edges {
                        node {
                            ...DynamicNavFragment
                            childItems {
                                edges {
                                    node {
                                        ...DynamicNavFragment
                                        childItems {
                                            edges {
                                                node {
                                                    ...DynamicNavFragment
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        Footer: wordpress {
            menu(id: $idFoot, idType: $idTypeFoot) {
                menuItems(where: { parentId: 0 }) {
                    edges {
                        node {
                            ...DynamicNavFragment
                            childItems {
                                edges {
                                    node {
                                        ...DynamicNavFragment
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    

    正在使用的片段是

    dynamic-nav-fields.graphql

    fragment DynamicNavFragment on WordpressMenuItem {
        id
        label
        path
        parentId
    }
    

    这一切都集中在一个全局 layout.tsx 组件中。我将在下面包含一个冗长的无头导航组件,但那是因为它有 3 层深,带有动态子子锚

    layout.tsx

    import { FooterFixture } from './Footer';
    import { HeadlessFooter } from './HeadlessFooter';
    import { HeadlessNavbar } from './HeadlessNavbar';
    import { Navbar } from './Navbar';
    import { Meta } from './Meta';
    import cn from 'classnames';
    import {
        DynamicNavQuery,
        useDynamicNavQuery,
        WordpressMenuNodeIdTypeEnum
    } from '@/graphql/generated/graphql';
    import {
        ApolloError,
        Button,
        Fallback,
        Modal,
        LandingHero
    } from '../UI';
    import { useGlobal } from '../Context';
    import { useAcceptCookies } from '@/lib/use-accept-cookies';
    import Head from 'next/head';
    import dynamic from 'next/dynamic';
    import { useRouter } from 'next/router';
    // import { LoginProps } from '../Auth/wp-login';
    
    const dynamicProps = {
        loading: () => <Fallback />
    };
    
    const LoginView = dynamic(
        () => import('../Auth/wp-login'),
        dynamicProps
    );
    
    const RegisterView = dynamic(
        () => import('../Auth/wp-register'),
        dynamicProps
    );
    
    const Featurebar = dynamic(
        () => import('./Featurebar'),
        dynamicProps
    );
    
    export interface LayoutProps {
        Header: DynamicNavQuery['Header'];
        Footer: DynamicNavQuery['Footer'];
        className?: string;
        title?: string;
        hero?: React.ReactNode;
        children?: React.ReactNode;
    }
    
    function AppLayout({
        Header,
        Footer,
        className,
        title,
        children,
        hero
    }: LayoutProps) {
        const { acceptedCookies, onAcceptCookies } = useAcceptCookies();
        const { displayModal, modalView, closeModal } = useGlobal();
        const { loading, error, data } = useDynamicNavQuery({
            variables: {
                idHead: 'Header',
                idTypeHead: WordpressMenuNodeIdTypeEnum.NAME,
                idTypeFoot: WordpressMenuNodeIdTypeEnum.NAME,
                idFoot: 'Footer'
            },
            notifyOnNetworkStatusChange: true
        });
        const router = useRouter();
        Header =
            data != null && data.Header != null ? data.Header : undefined;
        Footer =
            data != null && data.Footer != null ? data.Footer : undefined;
    
        return (
            <>
                <Head>
                    <title>{title ?? '✂ The Fade Room Inc. ✂'}</title>
                </Head>
                <Meta />
                {error ? (
                    <>
                        <ApolloError error={error} />
                    </>
                ) : loading && !error ? (
                    <Fallback />
                ) : (
                    <Navbar
                        Desktop={<HeadlessNavbar header={Header} />}
                        Mobile={
                            <HeadlessNavbar
                                header={Header}
                                className={
                                    'block px-3 py-2 rounded-md text-lg sm:text-base font-sans font-semibold text-secondary-0 hover:bg-redditSearch'
                                }
                            />
                        }
                    />
                )}
                <>
                    {router.pathname === '/' ? <LandingHero /> : hero}
                    <Modal open={displayModal} onClose={closeModal}>
                        {modalView === 'LOGIN_VIEW' && <LoginView />}
                        {modalView === 'SIGNUP_VIEW' && <RegisterView />}
                    </Modal>
                    <div className={cn('bg-redditSearch', className)}>
                        <main className='fit'>
                            {children}
                            {error ? (
                                <>
                                    <ApolloError error={error} />
                                </>
                            ) : loading && !error ? (
                                <Fallback />
                            ) : (
                                <FooterFixture
                                    children={<HeadlessFooter footer={Footer} />}
                                />
                            )}
                        </main>
                        <div className='font-sans z-150'>
                            <Featurebar
                                title='This site uses cookies to improve your experience. By clicking, you agree to our Privacy Policy.'
                                hide={
                                    acceptedCookies ? !!acceptedCookies : !acceptedCookies
                                }
                                className='prose-lg sm:prose-xl bg-opacity-90 sm:text-center'
                                action={
                                    <Button
                                        type='submit'
                                        variant='slim'
                                        className='mx-auto text-secondary-0 text-center rounded-xl border-secondary-0 border-1 hover:bg-gray-700 hover:bg-opacity-80 hover:border-secondary-0 duration-500 ease-in-out transform-gpu transition-colors'
                                        onClick={() => onAcceptCookies()}
                                    >
                                        Accept Cookies
                                    </Button>
                                }
                            />
                        </div>
                    </div>
                </>
            </>
        );
    }
    
    export default AppLayout;
    
    

    useDynamicNavQuery 函数注入数据的HeadlessNavbar 组件在此处映射。我一直想把它分开,但这有点痛苦。

    Layout/HeadlessNavbar/headless-navbar.tsx

    import { useState, FC, useRef, useEffect } from 'react';
    import cn from 'classnames';
    import { useRouter } from 'next/router';
    import Link from 'next/link';
    import { Button } from '../../UI';
    import { Transition, Listbox } from '@headlessui/react';
    import { NavArrow } from '@/components/UI/Icons';
    import { DynamicNavQuery } from '@/graphql/generated/graphql';
    import css from './headless-navbar.module.css';
    import { DynamicNavSubAnchors } from '@/types/dynamic-nav';
    import throttle from 'lodash.throttle';
    
    export interface HeadlessNavbarProps
        extends DynamicNavSubAnchors {
        header: DynamicNavQuery['Header'];
        className?: string;
    }
    
    const HeadlessNavbar: FC<HeadlessNavbarProps> = ({
        header,
        className,
        node
    }) => {
        const [isOpen, setIsOpen] = useState(false);
        const [subOpen, setSubOpen] = useState(false);
        const [hasScrolled, setHasScrolled] = useState(false);
        const [selectedCategory, setSelectedCategory] = useState(node);
        const { pathname } = useRouter();
        const isOpenRef = useRef(isOpen);
        const refAcceptor =
            useRef() as React.MutableRefObject<HTMLDivElement>;
    
        useEffect(() => {
            const handleScroll = throttle(() => {
                const offset = window.scrollY ?? 0;
                const { scrollTop } = document.documentElement;
                const scrolled = scrollTop > offset;
                setHasScrolled(scrolled);
                setIsOpen(isOpenRef.current);
            }, 200);
            document.addEventListener('scroll', handleScroll);
            return () => {
                document.removeEventListener('scroll', handleScroll);
            };
        }, [hasScrolled, isOpenRef.current]);
        return (
            <>
                {header?.menu?.menuItems?.edges &&
                header.menu.menuItems.edges.length > 0 ? (
                    header.menu.menuItems.edges.map((top, i) => {
                        return top != null &&
                            top.node != null &&
                            top.node.label != null ? (
                            <>
                                {top.node.childItems?.edges &&
                                top.node.childItems.edges.length !== 0 ? (
                                    <>
                                        <Link
                                            href={top.node.path}
                                            as={top.node.path}
                                            passHref
                                            scroll={true}
                                            key={top.node.id}
                                        >
                                            <a
                                                id='top'
                                                className={cn(className, {
                                                    [css.activeWithChildren]: pathname === top.node.path,
                                                    [css.linkWithChildren]: pathname !== top.node.path
                                                })}
                                            >
                                                <p className='inline-flex'>{top.node.label}</p>
                                            </a>
                                        </Link>
                                        <button
                                            onClick={() => setIsOpen(!isOpen)}
                                            id='sub-menu'
                                            aria-haspopup={true}
                                            aria-expanded={true}
                                            type='button'
                                            className={cn(css.topButton, {
                                                '-rotate-180': isOpen,
                                                'rotate-0': !isOpen
                                            })}
                                        >
                                            <NavArrow className='select-none w-5 h-5' />
                                        </button>
                                    </>
                                ) : top.node.childItems?.edges &&
                                  top.node.childItems.edges.length < 1 ? (
                                    <Link
                                        href={top.node.path}
                                        as={top.node.path}
                                        passHref
                                        scroll={true}
                                        key={top.node.id}
                                    >
                                        <a
                                            id='top'
                                            className={cn(className, {
                                                [css.active]: pathname === top.node.path,
                                                [css.link]: pathname !== top.node.path
                                            })}
                                        >
                                            <p>{top.node.label}</p>
                                        </a>
                                    </Link>
                                ) : (
                                    <></>
                                )}
                                {top.node.childItems != null &&
                                top.node.childItems.edges != null &&
                                top.node.childItems.edges.length > 0 ? (
                                    <div className='lg:relative z-150 -ml-2'>
                                        <Transition
                                            show={isOpen}
                                            enter='transition ease-out duration-200 '
                                            enterFrom='transform opacity-0 translate-y-1'
                                            enterTo='transform opacity-100 translate-y-0'
                                            leave='transition ease-in duration-150'
                                            leaveFrom='transform opacity-100 translate-y-0'
                                            leaveTo='transform opacity-0 translate-y-1'
                                        >
                                            <div className={cn(css.transitionAlpha, '')}>
                                                <div
                                                    className={css.transitionBeta}
                                                    ref={refAcceptor}
                                                    role='menu'
                                                    aria-orientation='vertical'
                                                    aria-labelledby='sub-menu'
                                                >
                                                    <div className={css.transitionGamma}>
                                                        {top!.node!.childItems!.edges!.map((sub, j) => {
                                                            return sub != null &&
                                                                sub.node != null &&
                                                                sub.node.label != null &&
                                                                sub.node.parentId != null ? (
                                                                <Listbox
                                                                    key={sub.node.path}
                                                                    value={selectedCategory}
                                                                    onChange={setSelectedCategory}
                                                                >
                                                                    {({ open }) => (
                                                                        <>
                                                                            <div className={cn(css.divOpen)}>
                                                                                <p className='text-base font-medium pr-2 bg-redditNav font-sans inline-flex py-2 ml-4'>
                                                                                    {sub!.node!.label!}
                                                                                    <Listbox.Button
                                                                                        as='button'
                                                                                        aria-haspopup={true}
                                                                                        id='sub'
                                                                                        aria-expanded={true}
                                                                                        onClick={() => setSubOpen(!subOpen)}
                                                                                        className={cn(css.bottomButton, {
                                                                                            ' bg-redditNav  -rotate-180': open,
                                                                                            ' bg-redditNav  rotate-0': !open
                                                                                        })}
                                                                                    >
                                                                                        <NavArrow className='select-none w-5 h-5' />
                                                                                    </Listbox.Button>
                                                                                </p>
                                                                            </div>
                                                                            <Transition
                                                                                show={open}
                                                                                enter='transition ease-out duration-100'
                                                                                enterFrom='transform opacity-0 scale-95'
                                                                                enterTo='transform opacity-100 scale-100'
                                                                                leave='transition ease-in duration-75'
                                                                                leaveFrom='transform opacity-100 scale-100'
                                                                                leaveTo='transform opacity-0 scale-95'
                                                                            >
                                                                                <Listbox.Options
                                                                                    static
                                                                                    className='outline-none select-none focus:outline-none'
                                                                                >
                                                                                    {sub!.node!.childItems != null &&
                                                                                    sub!.node!.childItems.edges != null &&
                                                                                    sub!.node!.childItems.edges.length > 0 ? (
                                                                                        sub!.node!.childItems!.edges!.map(
                                                                                            (subsub, k) => {
                                                                                                return subsub != null &&
                                                                                                    subsub.node != null &&
                                                                                                    subsub.node.label != null &&
                                                                                                    subsub.node.parentId != null ? (
                                                                                                    <>
                                                                                                        {open && (
                                                                                                            <Listbox.Option
                                                                                                                key={subsub.node.id}
                                                                                                                className={cn(
                                                                                                                    css.subsub,
                                                                                                                    'lg:text-base text-sm hover:bg-redditSearch font-medium list-none outline-none font-sans'
                                                                                                                )}
                                                                                                                value={subsub!.node!.label}
                                                                                                            >
                                                                                                                <>
                                                                                                                    <Link
                                                                                                                        href={subsub!.node!.path}
                                                                                                                        passHref
                                                                                                                        key={k++}
                                                                                                                        shallow={true}
                                                                                                                    >
                                                                                                                        <a
                                                                                                                            id='subsub'
                                                                                                                            className={cn(css.subsubanchor)}
                                                                                                                        >
                                                                                                                            {subsub!.node!.label}
                                                                                                                        </a>
                                                                                                                    </Link>
                                                                                                                </>
                                                                                                            </Listbox.Option>
                                                                                                        )}
                                                                                                    </>
                                                                                                ) : (
                                                                                                    <></>
                                                                                                );
                                                                                            }
                                                                                        )
                                                                                    ) : (
                                                                                        <></>
                                                                                    )}
                                                                                </Listbox.Options>
                                                                            </Transition>
                                                                        </>
                                                                    )}
                                                                </Listbox>
                                                            ) : (
                                                                <></>
                                                            );
                                                        })}
                                                    </div>
                                                </div>
                                            </div>
                                        </Transition>
                                    </div>
                                ) : (
                                    <></>
                                )}
                            </>
                        ) : (
                            <></>
                        );
                    })
                ) : (
                    <></>
                )}
            </>
        );
    };
    
    export default HeadlessNavbar;
    
    

    Here's the live site the code powers

    【讨论】:

      猜你喜欢
      • 2021-05-21
      • 1970-01-01
      • 2022-09-26
      • 1970-01-01
      • 2022-12-01
      • 2019-10-07
      • 1970-01-01
      • 2021-05-05
      • 2020-01-26
      相关资源
      最近更新 更多