-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Request: show examples of using GraphQL interfaces and (typed) fragment data #9
Comments
Thanks for this feedback @justlevine! We will be addressing this as soon as we get consensus on our RFC for multiple queries and implement this within the blueprints. |
When i try to add the editorBlocks inside the Component.query of the page.tsx i got this error: this is the whole page.tsx: import { gql } from "../__generated__";
import { WordPressBlock } from "@faustwp/blocks";
import Head from "next/head";
import EntryHeader from "../components/entry-header";
import Footer from "../components/footer";
import Header from "../components/header";
import { GetPageQuery } from "../__generated__/graphql";
import { DocumentNode } from 'graphql';
import { FaustTemplate } from "@faustwp/core";
import { flatListToHierarchical } from '@faustwp/core';
import { WordPressBlocksViewer } from '@faustwp/blocks';
import blocks from '../wp-blocks';
const Component: FaustTemplate<GetPageQuery> = ({loading, data}) => {
// Loading state for previews
if (loading) {
return <>Loading...</>;
}
const { title: siteTitle, description: siteDescription } =
data.generalSettings;
const menuItems = data.primaryMenuItems.nodes;
const { title, content, editorBlocks} = data.page;
const blockList = flatListToHierarchical(editorBlocks, { childrenKey: 'innerBlocks' });
return (
<>
<Head>
<title>{`${title} - ${siteTitle}`}</title>
</Head>
<Header
siteTitle={siteTitle}
siteDescription={siteDescription}
menuItems={menuItems}
/>
<main className="container">
<EntryHeader title={title} />
<div dangerouslySetInnerHTML={{ __html: content }} />
<WordPressBlocksViewer blocks={blockList} />
</main>
<Footer />
</>
);
};
Component.variables = ({ databaseId }, ctx) => {
return {
databaseId,
asPreview: ctx?.asPreview,
};
};
Component.query = gql(`
${blocks.CoreParagraph.fragments.entry}
${blocks.CoreColumns.fragments.entry}
${blocks.CoreColumn.fragments.entry}
${blocks.CoreCode.fragments.entry}
${blocks.CoreButtons.fragments.entry}
${blocks.CoreButton.fragments.entry}
${blocks.CoreQuote.fragments.entry}
${blocks.CoreImage.fragments.entry}
${blocks.CoreSeparator.fragments.entry}
${blocks.CoreList.fragments.entry}
${blocks.CoreHeading.fragments.entry}
query GetPage($databaseId: ID!, $asPreview: Boolean = false) {
page(id: $databaseId, idType: DATABASE_ID, asPreview: $asPreview) {
title
content
editorBlocks {
name
__typename
renderedHtml
id: clientId
parentId: parentClientId
...${blocks.CoreParagraph.fragments.key}
...${blocks.CoreColumns.fragments.key}
...${blocks.CoreColumn.fragments.key}
...${blocks.CoreCode.fragments.key}
...${blocks.CoreButtons.fragments.key}
...${blocks.CoreButton.fragments.key}
...${blocks.CoreQuote.fragments.key}
...${blocks.CoreImage.fragments.key}
...${blocks.CoreSeparator.fragments.key}
...${blocks.CoreList.fragments.key}
...${blocks.CoreHeading.fragments.key}
}
}
generalSettings {
title
description
}
primaryMenuItems: menuItems(where: { location: PRIMARY }) {
nodes {
id
uri
path
label
parentId
cssClasses
menu {
node {
name
}
}
}
}
}
`);
export default Component; I would be grateful for any help. |
I use import { WordPressTemplate } from '@faustwp/core/dist/mjs/getWordPressProps';
import dynamic from 'next/dynamic';
import { gql } from '@graphqlTypes/gql';
const Component = dynamic( () =>
import( '../features/WpTemplates/Page' ).then( ( mod ) => mod.Page )
);
const Page: WordPressTemplate = ( props ) => {
return <Component { ...props } />;
};
Page.variables = ( { uri } ) => {
return {
uri,
};
};
Page.query = gql( `
query GetPageNode($uri: ID!) {
siteConfig {
...SiteIdentityFrag
...FooterSettingsFrag
}
...PrimaryMenuItemsFrag
currentPage: page(id: $uri, idType: URI) {
id
uri
title
editorBlocks {
...BlockContentEditorBlockFrag
}
...FeaturedImageFrag
...NodeWithSeoFrag
pageSettings {
axewpPageHeader
}
}
}
` );
export default Page; The dynamic import is because Faust loads all the possible templates in app.ts 🤷♂️ In that case, it's the dynamic component that gets wrapped as a import dynamic from 'next/dynamic';
import { Main } from '@/components/elements/Main/Main';
import { PageHeader } from '@/components/elements/PageHeader/PageHeader';
import { Header } from '@/components/layouts/Header/Header';
import { Layout } from '@/components/layouts/Layout/Layout';
import { BlockContent } from '@/features/WpBlocks/components/BlockContent';
import { getFragmentData } from '@graphqlTypes/fragment-masking';
import {
MediaItemFragFragmentDoc,
FeaturedImageFragFragmentDoc,
FooterSettingsFragFragmentDoc,
NodeWithSeoFragFragmentDoc,
PrimaryMenuItemsFragFragmentDoc,
SiteIdentityFragFragmentDoc,
BlockContentEditorBlockFragFragment,
GetPageNodeQuery,
MenuItemNodeFragFragment,
SeoFragFragment,
} from '@graphqlTypes/graphql';
import type { FaustTemplate } from '@faustwp/core/dist/mjs/getWordPressProps';
const Footer = dynamic( () =>
import( '../../components/layouts/Footer/Footer' ).then( ( mod ) => mod.Footer )
);
export const Page: FaustTemplate< GetPageNodeQuery > = ( { data, loading } ) => {
const identityFrag = getFragmentData( SiteIdentityFragFragmentDoc, data?.siteConfig );
const logo = getFragmentData(
MediaItemFragFragmentDoc,
identityFrag?.identity?.axewpLogoLight?.node
);
const footerFrag = getFragmentData( FooterSettingsFragFragmentDoc, data?.siteConfig );
const footer = footerFrag?.footerSettings?.axewpFooterContent;
const primaryMenuFrag = getFragmentData( PrimaryMenuItemsFragFragmentDoc, data );
const menu = primaryMenuFrag?.primaryMenuItems?.nodes;
const seoFrag = getFragmentData( NodeWithSeoFragFragmentDoc, data?.currentPage );
const seo = seoFrag?.seo;
const editorBlocks = data?.currentPage?.editorBlocks;
const pageTitle =
data?.currentPage?.pageSettings?.axewpPageHeader || data?.currentPage?.title || '';
const featuredImageFrag = getFragmentData( FeaturedImageFragFragmentDoc, data?.currentPage );
const featuredImage = getFragmentData(
MediaItemFragFragmentDoc,
featuredImageFrag?.featuredImage?.node
);
return (
<Layout loading={ !! loading } seo={ seo as SeoFragFragment }>
<Header logo={ logo } menu={ menu as MenuItemNodeFragFragment[] } />
<Main
className="wp-block-group is-layout-constrained"
style={ {
marginTop: 'var(--wp--preset--spacing--30)',
} }
>
<PageHeader
title={ pageTitle }
image={ featuredImage }
className="wp-block-group alignwide has-global-padding"
/>
{ !! editorBlocks?.length && (
<BlockContent blocks={ editorBlocks as BlockContentEditorBlockFragFragment[] } />
) }
</Main>
<Footer content={ footer ?? '' } />
</Layout>
);
}; |
Thank you for your reply @justlevine! I tried the approach you mentioned above but still no luck, and the same error. :/ import { gql } from "../__generated__";
import { WordPressTemplate } from '@faustwp/core/dist/mjs/getWordPressProps';
import dynamic from 'next/dynamic';
import blocks from '../wp-blocks';
const Component = dynamic( () =>
import( '../features/WpTemplates/Page' ).then( ( mod ) => mod.Page )
);
const Page: WordPressTemplate = ( props ) => {
return <Component { ...props } />;
};
Page.variables = ({ databaseId }, ctx) => {
return {
databaseId,
asPreview: ctx?.asPreview,
};
};
Page.query = gql(`
query GetPage($databaseId: ID!, $asPreview: Boolean = false) {
generalSettings {
title
description
}
primaryMenuItems: menuItems(where: { location: PRIMARY }) {
nodes {
id
uri
path
label
parentId
cssClasses
menu {
node {
name
}
}
}
}
currentPage: page(id: $databaseId, idType: DATABASE_ID, asPreview: $asPreview) {
title
content
editorBlocks {
name
__typename
renderedHtml
id: clientId
parentId: parentClientId
...${blocks.CoreParagraph.fragments.key}
...${blocks.CoreColumns.fragments.key}
...${blocks.CoreColumn.fragments.key}
...${blocks.CoreCode.fragments.key}
...${blocks.CoreButtons.fragments.key}
...${blocks.CoreButton.fragments.key}
...${blocks.CoreQuote.fragments.key}
...${blocks.CoreImage.fragments.key}
...${blocks.CoreSeparator.fragments.key}
...${blocks.CoreList.fragments.key}
...${blocks.CoreHeading.fragments.key}
}
}
}
`);
export default Page; and the WpTemplates/Page.tsx: import Head from "next/head";
import EntryHeader from "../../components/entry-header";
import Footer from "../../components/footer";
import Header from "../../components/header";
import { GetPageQuery } from "../../__generated__/graphql";
import type { FaustTemplate } from '@faustwp/core/dist/mjs/getWordPressProps';
import { flatListToHierarchical } from '@faustwp/core';
import { WordPressBlocksViewer } from '@faustwp/blocks';
export const Page: FaustTemplate<GetPageQuery> = ({ data, loading }) => {
// Loading state for previews
if (loading) {
return <>Loading...</>;
}
const { title: siteTitle, description: siteDescription } =
data.generalSettings;
const menuItems = data.primaryMenuItems.nodes;
const { title, content, editorBlocks} = data.currentPage;
const blockList = flatListToHierarchical(editorBlocks, { childrenKey: 'innerBlocks' });
return (
<>
<Head>
<title>{`${title} - ${siteTitle}`}</title>
</Head>
<Header
siteTitle={siteTitle}
siteDescription={siteDescription}
menuItems={menuItems}
/>
<main className="container">
<EntryHeader title={title} />
<div dangerouslySetInnerHTML={{ __html: content }} />
<WordPressBlocksViewer blocks={blockList} />
</main>
<Footer />
</>
);
}; can't figure it out what i'm doing wrong |
Hi @mariusorani, if you are still experiencing this, could you open a new issue on the faustjs repo? |
@justlevine Sorry for the lack of traction on this. we've been in the transition from using an internal Jira board to now using GitHub projects. I've added this item to our backlog, but not sure when we can prioritize it. When we pull this into progress we'll update you here! |
WordPress-flavored Headless is simplest when we design our queries using GraphQL interfaces and reusable fragments. We see this pattern in faust already with content blocks.
GraphQL-Codegen handles this with the
useFragment()
decorator, a recent pattern that that's not the most obvious to implement when using Apollo.It would be extremely helpful if this scaffold included examples that show users how to effectively employ these patterns with Faust.
For example: a
wp-templates/singular
that usesnodeByUri
to get data for either a post or page, aprimaryMenuItems
that passes when strict ts is enabled, or a ts-valid setup for Faust Blocks that doesnt throw linting errors against theContentBlock
prop type, since the attribute fragments are only stored as refs until decorated.The text was updated successfully, but these errors were encountered: