From 9b6c8d6f3af138525d3ce3834758e356bb385f4d Mon Sep 17 00:00:00 2001 From: William Johnston Date: Mon, 11 Oct 2021 12:53:18 -0700 Subject: [PATCH 01/11] doc: (#519) adding examples for getStaticPaths --- docs/next/guides/ssr-ssg.mdx | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docs/next/guides/ssr-ssg.mdx b/docs/next/guides/ssr-ssg.mdx index 80a1ecceb..1812c0f18 100644 --- a/docs/next/guides/ssr-ssg.mdx +++ b/docs/next/guides/ssr-ssg.mdx @@ -56,6 +56,65 @@ The reason `MyPage` and `client` are passed to `getNextStaticProps` is because u This allows the developer to not have to think about batching/constructing queries, or data fetching. You are able to write your page as if you will be using Client-side Rendering (CSR). Then, you add the `getStaticProps` function above and can take advantage of SSG! +### How To Handle `getStaticPaths` + +Next.js supports [SSG with `getStaticPaths`](https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation) as well. This function is used to build a list of paths that can be used to statically generate your site. This function should be used when you have a dynamic page that needs to be statically generated (e.g. `[postSlug].tsx`). In the `getStaticPaths` function you have the option to return the paths that you have several options that inform Next.js how you want to statically generate your pages. Consider the following examples: + +#### Statically Generate All Your Pages Upon Request + +If you don't know exactly how you want to statically generate your site, a good option for `getStaticPaths` is to inform Next.js not to generate any HTML at build time, but to generated it on-the-fly as new requests come in. You can do this as follows: + +```tsx title=src/pages/posts/[postSlug]/index.tsx +export function getStaticPaths() { + return { + paths: [], + fallback: 'blocking', + }; +} +``` + +The above code will tell Next.js not to generate any pages up front. Then, as requests come in they will be generated server-side and stored for subsequent requests. Read more about [`fallback: 'blocking'`](https://nextjs.org/docs/basic-features/data-fetching#fallback-blocking). + +#### Statically Generate **Some** Of Your Pages At Build Time Based On A Query + +Maybe you want to generate a specific set of posts during build time. Perhaps you want to generate the most recent posts, or maybe you want to generate posts that receive a lot of traffic. You can do this by providing paths to Next.js that are based on a query as follows: + +```tsx title=src/pages/posts/[postSlug]/index.tsx +import { client } from 'client'; + +export async function getStaticPaths() { + const values = await client.client.inlineResolved(() => { + return client.client.query + .posts({ + first: 5, + }) + ?.nodes?.map((node) => node?.uri); + }); + const paths = []; + + if (Array.isArray(values)) { + paths.push( + ...values + .filter((value) => { + return typeof value === 'string'; + }), + ); + } + + return { + paths, + fallback: 'blocking', + }; +``` + +> **NOTE**: The code above assumes you have your permalink structure set to `/posts/%postname%/` in WordPress. You can add additional logic here to format the proper URL if that is not the case. + +The code above will perform an inline query to WordPress in order to get the 5 most recent posts. Then it will create a list of paths based on the post URIs. In this case we are not rendering all the post pages up front, so some will be dynamically generated on-the-fly using the `fallback: 'blocking'` feature in Next.js. + + +The above scenarios are most common, but there are other options for [`getStaticPaths`](https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation) that might be useful depending upon your needs. + + ## SSR Using `getNextServerSideProps` This helper function lets you server side render your page with WordPress data. The function should be returned from `getServerSideProps`: From 96a94c27e7afc334b5ba68135c237da038a354de Mon Sep 17 00:00:00 2001 From: Blake Wilson Date: Thu, 14 Oct 2021 12:43:48 -0500 Subject: [PATCH 02/11] Update API Router auth import docs --- docs/next/guides/authentication.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/next/guides/authentication.mdx b/docs/next/guides/authentication.mdx index 5a259b777..84186d846 100644 --- a/docs/next/guides/authentication.mdx +++ b/docs/next/guides/authentication.mdx @@ -22,7 +22,7 @@ Before you get started with implementing an authentication strategy, you'll need ```ts title=src/pages/api/faust/[[...route]].ts import 'faust.config'; -import { apiRouter } from '@faustjs/core'; +import { apiRouter } from '@faustjs/core/api'; export default apiRouter; ``` From 6f26203b33ff82bf219084bd4bb5b2f8087e4856 Mon Sep 17 00:00:00 2001 From: Blake Wilson Date: Thu, 14 Oct 2021 12:56:09 -0500 Subject: [PATCH 03/11] Update API Router imports to use `@faustjs/core/api` --- docs/next/guides/post-page-previews.mdx | 2 +- docs/next/reference/api-router.mdx | 4 ++-- packages/core/src/server/router/index.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/next/guides/post-page-previews.mdx b/docs/next/guides/post-page-previews.mdx index 4dec226f7..fd9843967 100644 --- a/docs/next/guides/post-page-previews.mdx +++ b/docs/next/guides/post-page-previews.mdx @@ -60,7 +60,7 @@ Next, you will need to create the `apiRouter`. This sets up the Faust.js API end ```ts import 'faust.config'; -import { apiRouter } from '@faustjs/core'; +import { apiRouter } from '@faustjs/core/api'; export default apiRouter; ``` diff --git a/docs/next/reference/api-router.mdx b/docs/next/reference/api-router.mdx index 3055b925d..86e421334 100644 --- a/docs/next/reference/api-router.mdx +++ b/docs/next/reference/api-router.mdx @@ -27,7 +27,7 @@ Now, add the following content to your newly created `[[...route]].ts` file: ```tsx title="src/pages/api/faust/[[...route]].ts" import 'faust.config'; -import { apiRouter } from '@faustjs/core'; +import { apiRouter } from '@faustjs/core/api'; export default apiRouter; ``` @@ -69,7 +69,7 @@ Finally, the content of `src/pages/api/headless/[[...route]].ts` would be: ```ts title="src/pages/api/headless/[[...route]].ts" import 'faust.config'; -import { apiRouter } from '@faustjs/core'; +import { apiRouter } from '@faustjs/core/api'; export default apiRouter; ``` diff --git a/packages/core/src/server/router/index.ts b/packages/core/src/server/router/index.ts index dea429060..a4db86a8b 100644 --- a/packages/core/src/server/router/index.ts +++ b/packages/core/src/server/router/index.ts @@ -14,7 +14,7 @@ import { * @example ```ts * // filename: pages/api/faust/[[...route]].ts * import 'faust.config'; - * import { apiRouter } from '@faustjs/core'; + * import { apiRouter } from '@faustjs/core/api'; * * export default apiRouter; * ``` From c719d7c861404014592837015bb2e3d3f6aefc09 Mon Sep 17 00:00:00 2001 From: Blake Wilson Date: Fri, 5 Nov 2021 09:29:43 -0700 Subject: [PATCH 04/11] Breakout Hooks into individual Pages (#631) * docs: break out hooks * Update links to appropriate hooks url --- docs/next/guides/authentication.mdx | 6 +- docs/next/reference/custom-hooks.mdx | 432 ----------------------- docs/next/reference/hooks/gqty-hooks.mdx | 25 ++ docs/next/reference/hooks/useAuth.mdx | 86 +++++ docs/next/reference/hooks/useLogin.mdx | 77 ++++ docs/next/reference/hooks/useLogout.mdx | 42 +++ docs/next/reference/hooks/usePage.mdx | 57 +++ docs/next/reference/hooks/usePost.mdx | 59 ++++ docs/next/reference/hooks/usePosts.mdx | 65 ++++ docs/next/reference/hooks/usePreview.mdx | 38 ++ docs/tutorial/querying-data.mdx | 31 +- internal/website/sidebars.js | 47 ++- packages/next/CHANGELOG.md | 2 +- packages/next/src/gqty/hooks/index.ts | 14 +- 14 files changed, 521 insertions(+), 460 deletions(-) delete mode 100644 docs/next/reference/custom-hooks.mdx create mode 100644 docs/next/reference/hooks/gqty-hooks.mdx create mode 100644 docs/next/reference/hooks/useAuth.mdx create mode 100644 docs/next/reference/hooks/useLogin.mdx create mode 100644 docs/next/reference/hooks/useLogout.mdx create mode 100644 docs/next/reference/hooks/usePage.mdx create mode 100644 docs/next/reference/hooks/usePost.mdx create mode 100644 docs/next/reference/hooks/usePosts.mdx create mode 100644 docs/next/reference/hooks/usePreview.mdx diff --git a/docs/next/guides/authentication.mdx b/docs/next/guides/authentication.mdx index 84186d846..071cd2ee4 100644 --- a/docs/next/guides/authentication.mdx +++ b/docs/next/guides/authentication.mdx @@ -44,7 +44,7 @@ Redirect based authentication is the default strategy in Faust.js. This strategy This strategy is great for use cases where your authenticated users are admins/editors/etc. and do not necessarily need a "white label" login/register experience. Typically, you would use the redirect strategy if your primary reason for authentication is previews. -Since Redirect based authentication is the default authentication method, there is no configuration needed on your end to use it. It comes out of the box, and you'll see it in action when using previews or the [`useAuth`](/docs/next/reference/custom-hooks#useauth) hook. +Since Redirect based authentication is the default authentication method, there is no configuration needed on your end to use it. It comes out of the box, and you'll see it in action when using previews or the [`useAuth`](/docs/next/reference/hooks/useAuth) hook. ### Local Based Authentication @@ -149,7 +149,7 @@ The `useLogin` hook exports an object with the following properties: - `data`: the response data from the login request. - `error`: the error from the login request. -For a more detailed explanation of the `useLogin` hook, see the [`useLogin` hook docs](/docs/next/reference/custom-hooks#uselogin) . +For a more detailed explanation of the `useLogin` hook, see the [`useLogin` hook docs](/docs/next/reference/hooks/useLogin) . Upon a successful login, a refresh token will be stored in a secure, http only cookie, as well as the access token in memory to use for subsequent authenticated requests. A login request can be confirmed it succeeded by checking for the `code` property in the `data` object. @@ -241,4 +241,4 @@ export default function Page() { } ``` -**Note:** The [`useAuth`](/docs/next/reference/custom-hooks#useauth) hook fetches the applicable tokens and ensures that the user is authenticated. Therefore, you should check for `isAuthenticated` prior to making authenticated requests, as doing so too early will result in a request without a valid access token. +**Note:** The [`useAuth`](/docs/next/reference/hooks/useAuth) hook fetches the applicable tokens and ensures that the user is authenticated. Therefore, you should check for `isAuthenticated` prior to making authenticated requests, as doing so too early will result in a request without a valid access token. diff --git a/docs/next/reference/custom-hooks.mdx b/docs/next/reference/custom-hooks.mdx deleted file mode 100644 index 96e705328..000000000 --- a/docs/next/reference/custom-hooks.mdx +++ /dev/null @@ -1,432 +0,0 @@ ---- -slug: /next/reference/custom-hooks -title: Useful Hooks For Data Fetching With Faust.js -description: Faust.js makes fetching data from Headless WordPress incredibly easy with special hooks. ---- - -When you use `getClient` from Faust.js to generate a GQty client, you will get some additional hooks that you can use to make your client more useful and make fetching data from Headless WordPress easier. The following hooks are available on the `client` object generated by `getClient`. - -### `usePost` - -The `usePost` hook provides the standard interface for getting a post from your Headless WordPress API. It also allows you to pass-in no arguments. When you do not pass arguments into `usePost` it will attempt to look at the URL params in order to determine how to get a post from your Headless WordPress API. In Next.js this means you will need to name your post page file in a particular way in order to get the proper URL params. Below are the possible names that will work automatically with Faust.js: - -- `[postId].tsx` -- `[postSlug].tsx` -- `[...postUri].tsx` - -Using the above names, Faust.js is able to apply the following logic to determine how to get a post from your Headless WordPress API: - -1. If `postId` is found in the URL params, Faust.js makes a request to retrieve a `post` from WordPress by `ID` -1. If `postSlug` is found in the URL params, Faust.js makes a request to retrieve a `post` from WordPress by `SLUG` -1. If `postUri` is found in the URL params, Faust.js makes a request to retrieve a `post` from WordPress by `URI` - -The following is an example of how to use the `usePost` hook with a `postSlug`: - -```tsx title=/src/pages/posts/[postSlug].tsx {5,6} -import { getNextStaticProps } from '@faustjs/next'; -import { client } from 'client'; - -export default function Page() { - const { usePost } = client; - const post = usePost(); - - return ( -
-

{post?.title()}

-
-
- ); -} -``` - -The above code will also work with `postId` and `postUri` depending upon what URL scheme you want to use. You may also want to fetch a specific post. Doing that might look similar to the following: - -```tsx {6-10} -import { getNextStaticProps } from '@faustjs/next'; -import { GetStaticPropsContext } from 'next'; -import { client, PostIdType } from 'client'; - -export default function Page() { - const { usePost } = client; - const post = usePost({ - id: 'hello-world', - idType: PostIdType.SLUG, - }); - - return ( -
-

{post?.title()}

-
-
- ); -} -``` - -### `usePosts` - -The `usePosts` hook provides the standard interface for getting a list of posts from your Headless WordPress API. It also allows you to pass-in no arguments. When you do not pass arguments into `usePosts` it will attempt to look at the URL params in order to determine how to get a list of posts from your Headless WordPress API. In Next.js this means you will need to name your post page file in a particular way in order to get the proper URL params. Below are the possible names that will work automatically with Faust.js: - -1. If `categoryId` is found in the URL params, a request is made to retrieve a list of posts for a `category` by `ID` -1. If `categorySlug` is found in the URL params, a request is made to retrieve a list of posts for a `category` by `SLUG` -1. If no URL params are found, a request is made to retrieve a list of posts without any filters - -The following is an example of how to use the `usePosts` hook with no URL params: - -```tsx title=src/pages/index.tsx {6-8,14-16} -import { getNextStaticProps } from '@faustjs/next'; -import { client } from 'client'; - -export default function Home() { - const { usePosts } = client; - const posts = usePosts({ - first: 6, - }); - - return ( - <> -

Recent Posts

-
    - {posts?.nodes.map((post) => ( -
  • {post.title()}
  • - ))} -
- - ); -} -``` - -The code above will get the first 6 posts from the Headless WordPress API. If you want to create a page that would pull posts associated with a specific category you can use the following code: - -```tsx title=src/pages/category/[categorySlug].tsx {6-8,14-16} -import { getNextStaticProps } from '@faustjs/next'; -import { client } from 'client'; - -export default function Home() { - const { usePosts } = client; - const posts = usePosts({ - first: 6, - }); - - return ( - <> -

Recent Posts

-
    - {posts?.nodes.map((post) => ( -
  • {post.title()}
  • - ))} -
- - ); -} -``` - -The code above will get the first 6 posts from the Headless WordPress API that are for the `categorySlug` defined in the URL params. - -For an example of `usePosts` with pagination, [take a look at our Next.js getting started example.](https://github.com/faustjs/framework/blob/canary/examples/next/getting-started/src/pages/posts/index.tsx#L17-L22) - -### `usePage` - -The `usePage` hook provides the standard interface for getting a page from your Headless WordPress API. It also allows you to pass-in no arguments. When you do not pass arguments into `usePage` it will attempt to look at the URL params in order to determine how to get a page from your Headless WordPress API. In Next.js this means you will need to name your page file in a particular way in order to get the proper URL params. Below are the possible names that will work automatically with Faust.js: - -- `[pageId].tsx` -- `[...pageUri].tsx` - -Using the above names, Faust.js is able to apply the following logic to determine how to get a page from your Headless WordPress API: - -1. If `pageId` is found in the URL params, Faust.js makes a request to retrieve a `page` from WordPress by `ID` -1. If `pageUri` is found in the URL params, Faust.js makes a request to retrieve a `page` from WordPress by `URI` - -The following is an example of how to use the `usePage` hook with a `pageUri`: - -```tsx title=/src/pages/[...pageUri].tsx {5,6} -import { getNextStaticProps } from '@faustjs/next'; -import { client } from 'client'; - -export default function Page() { - const { usePage } = client; - const page = usePage(); - - return ( -
-

{page?.title()}

-
-
- ); -} -``` - -The above code will also work with `pageId` and `pageUri` depending upon what URL scheme you want to use. You may also want to fetch a specific page. Doing that might look similar to the following: - -```tsx {6-10} -import { getNextStaticProps } from '@faustjs/next'; -import { GetStaticPropsContext } from 'next'; -import { client, PageIdType } from 'client'; - -export default function Page() { - const { usePost } = client; - const page = usePage({ - id: 'hello-world', - idType: PageIdType.SLUG, - }); - - return ( -
-

{page?.title()}

-
-
- ); -} -``` - -### `usePreview` - -The `usePreview` hook provides an abstraction around getting a preview `page` or `post` from the Headless WordPress API. When calling the `usePreview` hook on an appropriate preview page, the hook will determine if the preview is a `page` or `post` and will make a request to retrieve the proper preview content. - -The following example shows how to use the `usePreview` hook to render either a `post` or `page` from WordPress: - -```tsx title=src/pages/preview.tsx {14-17} -import { PageComponent } from './[...pageUri]'; -import { PostComponent } from './posts/[postSlug]'; -import { client } from 'client'; - -export default function Preview() { - const { usePreview } = client.auth; - const result = usePreview(); - - if (client.useIsLoading() || !result) { - return

loading...

; - } - - if (result.type === 'page') { - if (!result.page) { - return <>Not Found; - } - - return ; - } - - if (!result.post) { - return <>Not Found; - } - - return ; -} -``` - -### `useAuth` - -The `useAuth` hook provides a way to guarantee a users' authentication state, thus allowing you to control how a page's content is rendered. - -The `useAuth` hook accepts 1 argument of `UseAuthOptions`, which is an object that contains the following properties: - -```ts -const options = { - // Specify if the useAuth hook should facilitate the redirect to the appropriate url. - shouldRedirect: true; -} -``` - -By default, if the user is not authenticated, the page will redirect to the WordPress backend if the `authType` is `redirect`, and to the `loginPagePath` if `authType` is `local`. - -However, if the `shouldRedirect` option is `false`, the `useAuth` hook will **not** facilitate the redirect. - -The example below shows how to use the `useAuth` hook to render a page that requires authentication. If a user is authenticated, they will be shown the content. Otherwise, they will be redirected to the appropriate URL to authenticate: - -```tsx title=src/pages/gated-content.tsx {5} -import { client } from 'client'; - -export default function Gated() { - const { useAuth } = client.auth; - const { isLoading, isAuthenticated } = useAuth(); - - if (isLoading) { - return
Loading...
; - } - - return
Authenticated content
; -} -``` - -Additionally, the example below shows how to use `useAuth` with the `shouldRedirect` option set to `false`. This will disable the automatic redirect to the appropriate URL to authenticate, and allows you to control how the page's content is rendered in an unauthenticated state: - -```tsx title=src/pages/gated-content.tsx {5-7,13-15} -import { client } from 'client'; - -export default function Gated() { - const { useAuth } = client.auth; - const { isLoading, isAuthenticated, authResult } = useAuth({ - shouldRedirect: false, - }); - - if (isLoading) { - return
Loading...
; - } - - if (!isAuthenticated) { - return
You are not authenticated! Please login.
; - } - - return
Authenticated content
; -} -``` - -`useAuth` exports an object with the following properties: - -- `isLoading`: A boolean that indicates whether the `useAuth` function is currently checking if a user is authenticated. -- `isAuthenticated`: A boolean that indicates whether the user is authenticated. -- `authResult`: The result from checking if there is an authenticated user. - - If there is an authenticated user, the `authResult` will be `true`. Otherwise, the `authResult` will be an object with the following properties: - - ```js title="The authResult object when there is no authenticated user" - { - /** - * An absolute URL to the WordPress backend that the user should be redirected to in order to authenticate. - * This property is used for the "redirect" based authentication strategy - */ - redirect: 'xxxx'; - - /* - * A relative URL path to the local login page as specified in the `loginPagePath` option. - * This property is used for the "local" based authentication strategy - */ - login: 'xxxx'; - } - ``` - - The `authResult` can be helpful if you want to handle the redirection yourself, instead of the `useAuth` hook. - -### `useLogin` - -The `useLogin` hook provides an abstraction around obtaining an authorization code and fetching refresh/access tokens from WordPress, thus logging in a user to your Headless frontend. - -The following example shows how to use the `useLogin` hook to login a user: - -```tsx title=pages/login.tsx {9,18} -import { client } from 'client'; -import { useState } from 'react'; - -export default function Login() { - const { useLogin } = client.auth; - const [usernameEmail, setUserNameEmail] = useState(''); - const [password, setPassword] = useState(''); - - const { login, isLoading, data, error } = useLogin(); - - const errorMessage = data?.error || error?.message; - - return ( -
{ - e.preventDefault(); - - login(usernameEmail, password); - }} - > -
-
- -
-
- setUserNameEmail(e.target.value)} - id="usernameEmail" - /> -
- -
- -
-
- setPassword(e.target.value)} - id="password" - /> -
- -
- -
-
- - {errorMessage ?

Error: {errorMessage}

: null} -
- ); -} -``` - -`useLogin` exports an object with the following properties: - -- `login`: A function that initiates a request to obtain an authorization code via a GraphQL mutation by the provided `usernameEmail` and `password` arguments. Note that the `usernameEmail` argument is a string that can be either a username or an email address. -- `isLoading`: A boolean that indicates whether the `login` function is currently fetching an authorization code. -- `data`: An object that contains the response data from the `login` function. -- `error`: An object that contains the error data from the `login` function. - -When an authorization code is successfully fetched, `useLogin` will facilitate the request to the WPE Headless authorize endpoint to obtain the refresh/access tokens. From there, the tokens are stored properly, and the user is logged in. - -Additionally, if the login page URL contains a `redirect_uri` query parameter, the user will be redirected to the `redirect_uri` URL after the login is successful. - -### `useLogout` - -The `useLogout` hook provides a way to logout a user from your headless frontend. - -The following example shows how you could use the `useLogout` hook in a `logout.tsx` page: - -```tsx title="src/pages/logout.tsx" -import { client } from 'client'; -import { useRouter } from 'next/router'; -import { useEffect } from 'react'; -export default function Logout() { - const router = useRouter(); - const { isLoggedOut, logout } = client.auth.useLogout(); - useEffect(() => { - if (isLoggedOut !== undefined) { - return; - } - - // Initiate the logout process. - // This could also be called on a button click, for example, in a nav menu. - logout(); - }, [isLoggedOut, logout]); - - useEffect(() => { - if (isLoggedOut) { - // The user was successfully logged out. Redirect them. - router.push('/'); - } - }, [router, isLoggedOut]); - return <>Logging out...; -} -``` - -`useLogout` exports an object with the following properties: - -- `logout`: a function that initiates a request to logout the user by clearing their refresh token from the cookie. -- `isLoggedOut`: `undefiend` until the `logout` function is called. Then a `boolean` that indicates whether the user was successfully logged out -- `isLoading`: A boolean that indicates whether the `logout` function is currently logging out the user. - -### Custom Queries and Mutations - -GQty publishes the following hooks that can be used for custom queries, mutations, or subscriptions: - -- [`useQuery`](https://gqty.dev/docs/react/fetching-data#usequery) - - Make any query request to the Headless WordPress API -- [`useLazyQuery`](https://gqty.dev/docs/react/fetching-data#uselazyquery) -- [`useTransactionQuery`](https://gqty.dev/docs/react/fetching-data#usetransactionquery) -- [`useMutation`](https://gqty.dev/docs/react/mutations#usemutation) - - Make any mutation request to the Headless WordPress API -- [`useSubscription`](https://gqty.dev/docs/react/subscriptions#usesubscription) - -For example, you may want to get a list of your content types: - -```tsx -const { useQuery } = client; - -const contentTypes = useQuery().contentTypes()?.nodes; -``` - -`useQuery`, along with all the other hooks, are typed. So you'll be able to see exactly what kind of data you have access to via your IDE's intellisense. diff --git a/docs/next/reference/hooks/gqty-hooks.mdx b/docs/next/reference/hooks/gqty-hooks.mdx new file mode 100644 index 000000000..f9994a0fd --- /dev/null +++ b/docs/next/reference/hooks/gqty-hooks.mdx @@ -0,0 +1,25 @@ +--- +slug: /next/reference/hooks/gqty-hooks +title: GQty Hooks +description: How to use the GQty related hooks for fetching data +--- + +There may be instances where the built in Faust.js hooks do not satisfy your data fetching requirements. Thankfully, GQty publishes the following hooks that can be used for custom queries, mutations, or subscriptions: + +- [`useQuery`](https://gqty.dev/docs/react/fetching-data#usequery) + - Make any query request to the Headless WordPress API +- [`useLazyQuery`](https://gqty.dev/docs/react/fetching-data#uselazyquery) +- [`useTransactionQuery`](https://gqty.dev/docs/react/fetching-data#usetransactionquery) +- [`useMutation`](https://gqty.dev/docs/react/mutations#usemutation) + - Make any mutation request to the Headless WordPress API +- [`useSubscription`](https://gqty.dev/docs/react/subscriptions#usesubscription) + +For example, you may want to get a list of your content types: + +```tsx +const { useQuery } = client; + +const contentTypes = useQuery().contentTypes()?.nodes; +``` + +`useQuery`, along with all the other hooks, are typed. So you'll be able to see exactly what kind of data you have access to via your IDE's intellisense. diff --git a/docs/next/reference/hooks/useAuth.mdx b/docs/next/reference/hooks/useAuth.mdx new file mode 100644 index 000000000..367e231d4 --- /dev/null +++ b/docs/next/reference/hooks/useAuth.mdx @@ -0,0 +1,86 @@ +--- +slug: /next/reference/hooks/useAuth +title: useAuth +description: The useAuth hook provides a way to ensure that the user is authenticated. +--- + +The `useAuth` hook provides a way to guarantee a users' authentication state, thus allowing you to control how a page's content is rendered. + +The `useAuth` hook accepts 1 argument of `UseAuthOptions`, which is an object that contains the following properties: + +```ts +const options = { + // Specify if the useAuth hook should facilitate the redirect to the appropriate url. + shouldRedirect: true; +} +``` + +By default, if the user is not authenticated, the page will redirect to the WordPress backend if the `authType` is `redirect`, and to the `loginPagePath` if `authType` is `local`. + +However, if the `shouldRedirect` option is `false`, the `useAuth` hook will **not** facilitate the redirect. + +The example below shows how to use the `useAuth` hook to render a page that requires authentication. If a user is authenticated, they will be shown the content. Otherwise, they will be redirected to the appropriate URL to authenticate: + +```tsx title=src/pages/gated-content.tsx {5} +import { client } from 'client'; + +export default function Gated() { + const { useAuth } = client.auth; + const { isLoading, isAuthenticated } = useAuth(); + + if (isLoading) { + return
Loading...
; + } + + return
Authenticated content
; +} +``` + +Additionally, the example below shows how to use `useAuth` with the `shouldRedirect` option set to `false`. This will disable the automatic redirect to the appropriate URL to authenticate, and allows you to control how the page's content is rendered in an unauthenticated state: + +```tsx title=src/pages/gated-content.tsx {5-7,13-15} +import { client } from 'client'; + +export default function Gated() { + const { useAuth } = client.auth; + const { isLoading, isAuthenticated, authResult } = useAuth({ + shouldRedirect: false, + }); + + if (isLoading) { + return
Loading...
; + } + + if (!isAuthenticated) { + return
You are not authenticated! Please login.
; + } + + return
Authenticated content
; +} +``` + +`useAuth` exports an object with the following properties: + +- `isLoading`: A boolean that indicates whether the `useAuth` function is currently checking if a user is authenticated. +- `isAuthenticated`: A boolean that indicates whether the user is authenticated. +- `authResult`: The result from checking if there is an authenticated user. + + If there is an authenticated user, the `authResult` will be `true`. Otherwise, the `authResult` will be an object with the following properties: + + ```js title="The authResult object when there is no authenticated user" + { + /** + * An absolute URL to the WordPress backend that the user should be redirected to in order to authenticate. + * This property is used for the "redirect" based authentication strategy + */ + redirect: 'xxxx'; + + /* + * A relative URL path to the local login page as specified in the `loginPagePath` option. + * This property is used for the "local" based authentication strategy + */ + login: 'xxxx'; + } + ``` + + The `authResult` can be helpful if you want to handle the redirection yourself, instead of the `useAuth` hook. diff --git a/docs/next/reference/hooks/useLogin.mdx b/docs/next/reference/hooks/useLogin.mdx new file mode 100644 index 000000000..eb2570d22 --- /dev/null +++ b/docs/next/reference/hooks/useLogin.mdx @@ -0,0 +1,77 @@ +--- +slug: /next/reference/hooks/useLogin +title: useLogin +description: The useLogin hook provides a way to log in a user +--- + +The `useLogin` hook provides an abstraction around obtaining an authorization code and fetching refresh/access tokens from WordPress, thus logging in a user to your Headless frontend. + +The following example shows how to use the `useLogin` hook to login a user: + +```tsx title=pages/login.tsx {9,18} +import { client } from 'client'; +import { useState } from 'react'; + +export default function Login() { + const { useLogin } = client.auth; + const [usernameEmail, setUserNameEmail] = useState(''); + const [password, setPassword] = useState(''); + + const { login, isLoading, data, error } = useLogin(); + + const errorMessage = data?.error || error?.message; + + return ( +
{ + e.preventDefault(); + + login(usernameEmail, password); + }} + > +
+
+ +
+
+ setUserNameEmail(e.target.value)} + id="usernameEmail" + /> +
+ +
+ +
+
+ setPassword(e.target.value)} + id="password" + /> +
+ +
+ +
+
+ + {errorMessage ?

Error: {errorMessage}

: null} +
+ ); +} +``` + +`useLogin` exports an object with the following properties: + +- `login`: A function that initiates a request to obtain an authorization code via a GraphQL mutation by the provided `usernameEmail` and `password` arguments. Note that the `usernameEmail` argument is a string that can be either a username or an email address. +- `isLoading`: A boolean that indicates whether the `login` function is currently fetching an authorization code. +- `data`: An object that contains the response data from the `login` function. +- `error`: An object that contains the error data from the `login` function. + +When an authorization code is successfully fetched, `useLogin` will facilitate the request to the WPE Headless authorize endpoint to obtain the refresh/access tokens. From there, the tokens are stored properly, and the user is logged in. + +Additionally, if the login page URL contains a `redirect_uri` query parameter, the user will be redirected to the `redirect_uri` URL after the login is successful. diff --git a/docs/next/reference/hooks/useLogout.mdx b/docs/next/reference/hooks/useLogout.mdx new file mode 100644 index 000000000..e0b578613 --- /dev/null +++ b/docs/next/reference/hooks/useLogout.mdx @@ -0,0 +1,42 @@ +--- +slug: /next/reference/hooks/useLogout +title: useLogout Hook +description: The useLogout hook provides a way to logout a user +--- + +The `useLogout` hook provides a way to logout a user from your headless frontend. + +The following example shows how you could use the `useLogout` hook in a `logout.tsx` page: + +```tsx title="src/pages/logout.tsx" +import { client } from 'client'; +import { useRouter } from 'next/router'; +import { useEffect } from 'react'; +export default function Logout() { + const router = useRouter(); + const { isLoggedOut, logout } = client.auth.useLogout(); + useEffect(() => { + if (isLoggedOut !== undefined) { + return; + } + + // Initiate the logout process. + // This could also be called on a button click, for example, in a nav menu. + logout(); + }, [isLoggedOut, logout]); + + useEffect(() => { + if (isLoggedOut) { + // The user was successfully logged out. Redirect them. + router.push('/'); + } + }, [router, isLoggedOut]); + return <>Logging out...; +} +``` + +`useLogout` exports an object with the following properties: + +- `logout`: a function that initiates a request to logout the user by clearing their refresh token from the cookie. +- `isLoggedOut`: `undefiend` until the `logout` function is called. Then a `boolean` that indicates whether the user was successfully logged out +- `isLoading`: A boolean that indicates whether the `logout` function is currently logging out the user. diff --git a/docs/next/reference/hooks/usePage.mdx b/docs/next/reference/hooks/usePage.mdx new file mode 100644 index 000000000..8e1efb9ab --- /dev/null +++ b/docs/next/reference/hooks/usePage.mdx @@ -0,0 +1,57 @@ +--- +slug: /next/reference/hooks/usePage +title: usePage Hook +description: The usePage hook provides a standard way to get a wordpress page +--- + +The `usePage` hook provides the standard interface for getting a page from your Headless WordPress API. It also allows you to pass-in no arguments. When you do not pass arguments into `usePage` it will attempt to look at the URL params in order to determine how to get a page from your Headless WordPress API. In Next.js this means you will need to name your page file in a particular way in order to get the proper URL params. Below are the possible names that will work automatically with Faust.js: + +- `[pageId].tsx` +- `[...pageUri].tsx` + +Using the above names, Faust.js is able to apply the following logic to determine how to get a page from your Headless WordPress API: + +1. If `pageId` is found in the URL params, Faust.js makes a request to retrieve a `page` from WordPress by `ID` +1. If `pageUri` is found in the URL params, Faust.js makes a request to retrieve a `page` from WordPress by `URI` + +The following is an example of how to use the `usePage` hook with a `pageUri`: + +```tsx title=/src/pages/[...pageUri].tsx {5,6} +import { getNextStaticProps } from '@faustjs/next'; +import { client } from 'client'; + +export default function Page() { + const { usePage } = client; + const page = usePage(); + + return ( +
+

{page?.title()}

+
+
+ ); +} +``` + +The above code will also work with `pageId` and `pageUri` depending upon what URL scheme you want to use. You may also want to fetch a specific page. Doing that might look similar to the following: + +```tsx {6-10} +import { getNextStaticProps } from '@faustjs/next'; +import { GetStaticPropsContext } from 'next'; +import { client, PageIdType } from 'client'; + +export default function Page() { + const { usePost } = client; + const page = usePage({ + id: 'hello-world', + idType: PageIdType.SLUG, + }); + + return ( +
+

{page?.title()}

+
+
+ ); +} +``` diff --git a/docs/next/reference/hooks/usePost.mdx b/docs/next/reference/hooks/usePost.mdx new file mode 100644 index 000000000..dc028f64c --- /dev/null +++ b/docs/next/reference/hooks/usePost.mdx @@ -0,0 +1,59 @@ +--- +slug: /next/reference/hooks/usePost +title: usePost Hook +description: The usePost hook provides a standard way to get a WordPress post +--- + +The `usePost` hook provides the standard interface for getting a post from your Headless WordPress API. It also allows you to pass-in no arguments. When you do not pass arguments into `usePost` it will attempt to look at the URL params in order to determine how to get a post from your Headless WordPress API. In Next.js this means you will need to name your post page file in a particular way in order to get the proper URL params. Below are the possible names that will work automatically with Faust.js: + +- `[postId].tsx` +- `[postSlug].tsx` +- `[...postUri].tsx` + +Using the above names, Faust.js is able to apply the following logic to determine how to get a post from your Headless WordPress API: + +1. If `postId` is found in the URL params, Faust.js makes a request to retrieve a `post` from WordPress by `ID` +1. If `postSlug` is found in the URL params, Faust.js makes a request to retrieve a `post` from WordPress by `SLUG` +1. If `postUri` is found in the URL params, Faust.js makes a request to retrieve a `post` from WordPress by `URI` + +The following is an example of how to use the `usePost` hook with a `postSlug`: + +```tsx title=/src/pages/posts/[postSlug].tsx {5,6} +import { getNextStaticProps } from '@faustjs/next'; +import { client } from 'client'; + +export default function Page() { + const { usePost } = client; + const post = usePost(); + + return ( +
+

{post?.title()}

+
+
+ ); +} +``` + +The above code will also work with `postId` and `postUri` depending upon what URL scheme you want to use. You may also want to fetch a specific post. Doing that might look similar to the following: + +```tsx {6-10} +import { getNextStaticProps } from '@faustjs/next'; +import { GetStaticPropsContext } from 'next'; +import { client, PostIdType } from 'client'; + +export default function Page() { + const { usePost } = client; + const post = usePost({ + id: 'hello-world', + idType: PostIdType.SLUG, + }); + + return ( +
+

{post?.title()}

+
+
+ ); +} +``` diff --git a/docs/next/reference/hooks/usePosts.mdx b/docs/next/reference/hooks/usePosts.mdx new file mode 100644 index 000000000..3b3fced4c --- /dev/null +++ b/docs/next/reference/hooks/usePosts.mdx @@ -0,0 +1,65 @@ +--- +slug: /next/reference/hooks/usePosts +title: usePosts Hook +description: The usePosts hook provides a standard way to get multiple WordPress posts +--- + +The `usePosts` hook provides the standard interface for getting a list of posts from your Headless WordPress API. It also allows you to pass-in no arguments. When you do not pass arguments into `usePosts` it will attempt to look at the URL params in order to determine how to get a list of posts from your Headless WordPress API. In Next.js this means you will need to name your post page file in a particular way in order to get the proper URL params. Below are the possible names that will work automatically with Faust.js: + +1. If `categoryId` is found in the URL params, a request is made to retrieve a list of posts for a `category` by `ID` +1. If `categorySlug` is found in the URL params, a request is made to retrieve a list of posts for a `category` by `SLUG` +1. If no URL params are found, a request is made to retrieve a list of posts without any filters + +The following is an example of how to use the `usePosts` hook with no URL params: + +```tsx title=src/pages/index.tsx {6-8,14-16} +import { getNextStaticProps } from '@faustjs/next'; +import { client } from 'client'; + +export default function Home() { + const { usePosts } = client; + const posts = usePosts({ + first: 6, + }); + + return ( + <> +

Recent Posts

+
    + {posts?.nodes.map((post) => ( +
  • {post.title()}
  • + ))} +
+ + ); +} +``` + +The code above will get the first 6 posts from the Headless WordPress API. If you want to create a page that would pull posts associated with a specific category you can use the following code: + +```tsx title=src/pages/category/[categorySlug].tsx {6-8,14-16} +import { getNextStaticProps } from '@faustjs/next'; +import { client } from 'client'; + +export default function Home() { + const { usePosts } = client; + const posts = usePosts({ + first: 6, + }); + + return ( + <> +

Recent Posts

+
    + {posts?.nodes.map((post) => ( +
  • {post.title()}
  • + ))} +
+ + ); +} +``` + +The code above will get the first 6 posts from the Headless WordPress API that are for the `categorySlug` defined in the URL params. + +For an example of `usePosts` with pagination, [take a look at our Next.js getting started example.](https://github.com/faustjs/framework/blob/canary/examples/next/getting-started/src/pages/posts/index.tsx#L17-L22) diff --git a/docs/next/reference/hooks/usePreview.mdx b/docs/next/reference/hooks/usePreview.mdx new file mode 100644 index 000000000..8efcb888a --- /dev/null +++ b/docs/next/reference/hooks/usePreview.mdx @@ -0,0 +1,38 @@ +--- +slug: /next/reference/hooks/usePreview +title: usePreview Hook +description: The usePreview hook provides a way to get post preview data from WordPress +--- + +The `usePreview` hook provides an abstraction around getting a preview `page` or `post` from the Headless WordPress API. When calling the `usePreview` hook on an appropriate preview page, the hook will determine if the preview is a `page` or `post` and will make a request to retrieve the proper preview content. + +The following example shows how to use the `usePreview` hook to render either a `post` or `page` from WordPress: + +```tsx title=src/pages/preview.tsx {14-17} +import { PageComponent } from './[...pageUri]'; +import { PostComponent } from './posts/[postSlug]'; +import { client } from 'client'; + +export default function Preview() { + const { usePreview } = client.auth; + const result = usePreview(); + + if (client.useIsLoading() || !result) { + return

loading...

; + } + + if (result.type === 'page') { + if (!result.page) { + return <>Not Found; + } + + return ; + } + + if (!result.post) { + return <>Not Found; + } + + return ; +} +``` diff --git a/docs/tutorial/querying-data.mdx b/docs/tutorial/querying-data.mdx index 17f358f46..85168f8e3 100644 --- a/docs/tutorial/querying-data.mdx +++ b/docs/tutorial/querying-data.mdx @@ -16,15 +16,15 @@ The client we created in the previous tutorial gives us access to helpful [React ### Get Posts Using `usePosts` Hook -Let's use the [`usePosts`](../next/reference/custom-hooks#useposts) hook to get the latest posts from your headless WordPress site. +Let's use the [`usePosts`](../next/reference/hooks/usePosts) hook to get the latest posts from your headless WordPress site. ```tsx title=pages/posts.tsx {1,5-6} -import { client } from '../client' -import Post from "../components/post"; +import { client } from '../client'; +import Post from '../components/post'; export default function PostsPage() { - const {usePosts} = client - const posts = usePosts()?.nodes + const { usePosts } = client; + const posts = usePosts()?.nodes; return (
@@ -40,7 +40,7 @@ export default function PostsPage() { Let's also update the `Post` component to accept a `post` prop: ```tsx title=components/post.tsx {1,4,8} -import { Post as PostType } from "../client"; +import { Post as PostType } from '../client'; export interface PostProps { post: PostType; @@ -63,18 +63,18 @@ A couple of things to note here: The schema generated in the previous tutorial e Additionally, notice the `title` and `content` properties are functions. This is because you are able to specify if you want the rendered content or raw content. For example: ```tsx -post.title({format: PostObjectFieldFormatEnum.RAW}) +post.title({ format: PostObjectFieldFormatEnum.RAW }); ``` Let's go back to the `pages/posts.tsx` component and hook up the data we're fetching to the `Post` component: ```tsx title=pages/posts.tsx {12} -import { client } from '../client' -import Post from "../components/post"; +import { client } from '../client'; +import Post from '../components/post'; export default function PostsPage() { - const {usePosts} = client - const posts = usePosts()?.nodes + const { usePosts } = client; + const posts = usePosts()?.nodes; return (
@@ -89,7 +89,10 @@ export default function PostsPage() { Once those changes are made, navigate to [http://localhost:3000/posts](http://localhost:3000/posts) in your browser and you should see your posts. -Querying posts from headless WordPress +Querying posts from headless WordPress ### Get Data Using The `useQuery` Hook @@ -100,8 +103,8 @@ That is where the [`useQuery`](../next/reference/custom-hooks#custom-queries-and Let's display the site title and description using the `useQuery` hook. ```tsx title=pages/posts.tsx {5,10,11} -import { client } from "../client"; -import Post from "../components/post"; +import { client } from '../client'; +import Post from '../components/post'; export default function PostsPage() { const { usePosts, useQuery } = client; diff --git a/internal/website/sidebars.js b/internal/website/sidebars.js index 4da1ad067..0bb85063a 100644 --- a/internal/website/sidebars.js +++ b/internal/website/sidebars.js @@ -97,9 +97,50 @@ module.exports = { label: 'Reference', items: [ { - type: 'doc', - label: 'Custom Hooks', - id: 'next/reference/custom-hooks', + type: 'category', + label: 'Hooks', + items: [ + { + type: 'doc', + label: 'usePost Hook', + id: 'next/reference/hooks/usePost', + }, + { + type: 'doc', + label: 'usePosts Hook', + id: 'next/reference/hooks/usePosts', + }, + { + type: 'doc', + label: 'usePage Hook', + id: 'next/reference/hooks/usePage', + }, + { + type: 'doc', + label: 'usePreview Hook', + id: 'next/reference/hooks/usePreview', + }, + { + type: 'doc', + label: 'useAuth Hook', + id: 'next/reference/hooks/useAuth', + }, + { + type: 'doc', + label: 'useLogin Hook', + id: 'next/reference/hooks/useLogin', + }, + { + type: 'doc', + label: 'useLogout Hook', + id: 'next/reference/hooks/useLogout', + }, + { + type: 'doc', + label: 'GQty Hooks', + id: 'next/reference/hooks/gqty-hooks', + }, + ], }, { type: 'doc', diff --git a/packages/next/CHANGELOG.md b/packages/next/CHANGELOG.md index 47a074ad8..c6cc8b280 100644 --- a/packages/next/CHANGELOG.md +++ b/packages/next/CHANGELOG.md @@ -21,7 +21,7 @@ - 068f3c3: Introduced the `useLogout` hook to facilitate logging out a user - See https://faustjs.org/docs/next/reference/custom-hooks#uselogout for more details. + See https://faustjs.org/docs/next/reference/hooks/useLogout for more details. - Updated dependencies [068f3c3] - @faustjs/core@0.12.3 diff --git a/packages/next/src/gqty/hooks/index.ts b/packages/next/src/gqty/hooks/index.ts index 9a304c7c7..53683fb94 100644 --- a/packages/next/src/gqty/hooks/index.ts +++ b/packages/next/src/gqty/hooks/index.ts @@ -35,14 +35,14 @@ interface WithAuthHooks { /** * Faust.js hook to get preview data for a page or post. * - * @see https://faustjs.org/docs/next/reference/custom-hooks#usepreview + * @see https://faustjs.org/docs/next/reference/hooks/usePreview */ usePreview(): UsePreviewResponse; /** * Faust.js hook to ensure a user is authenticated. * - * @see https://faustjs.org/docs/next/reference/custom-hooks#useauth + * @see https://faustjs.org/docs/next/reference/hooks/useAuth */ useAuth(options?: UseAuthOptions): { isLoading: boolean; @@ -57,7 +57,7 @@ interface WithAuthHooks { * Faust.js hook to facilitate a login request. * * @param {UseLoginOptions} [options] - * @see https://faustjs.org/docs/next/reference/custom-hooks#uselogin + * @see https://faustjs.org/docs/next/reference/hooks/useLogin */ useLogin(options?: UseLoginOptions): { login: (usernameEmail: string, password: string) => Promise; @@ -80,7 +80,7 @@ interface WithAuthHooks { /** * Faust.js hook to facilitate a logout request. * - * @see https://faustjs.org/docs/next/reference/custom-hooks#uselogout + * @see https://faustjs.org/docs/next/reference/hooks/useLogout */ useLogout(): { isLoading: boolean; @@ -119,7 +119,7 @@ export interface NextClientHooks /** * Faust.js hook to get a list of posts. * - * @see https://faustjs.org/docs/next/reference/custom-hooks#useposts + * @see https://faustjs.org/docs/next/reference/hooks/usePosts */ usePosts( args?: Parameters[0], @@ -128,7 +128,7 @@ export interface NextClientHooks /** * Faust.js hook to get a single post. * - * @see https://faustjs.org/docs/next/reference/custom-hooks#usepost + * @see https://faustjs.org/docs/next/reference/hooks/usePost */ usePost( args?: Parameters[0], @@ -137,7 +137,7 @@ export interface NextClientHooks /** * Faust.js hook to get a single page. * - * @see https://faustjs.org/docs/next/reference/custom-hooks#usepage + * @see https://faustjs.org/docs/next/reference/hooks/usePage */ usePage( args?: Parameters[0], From 664ba05f36070a024eb0ce2a4bc3bf37ebd5d296 Mon Sep 17 00:00:00 2001 From: Blake Wilson Date: Fri, 5 Nov 2021 10:16:24 -0700 Subject: [PATCH 05/11] Logging queries guide --- docs/next/guides/logging-queries.mdx | 65 ++++++++++++++++++++++++++++ internal/website/sidebars.js | 5 +++ 2 files changed, 70 insertions(+) create mode 100644 docs/next/guides/logging-queries.mdx diff --git a/docs/next/guides/logging-queries.mdx b/docs/next/guides/logging-queries.mdx new file mode 100644 index 000000000..5644a1239 --- /dev/null +++ b/docs/next/guides/logging-queries.mdx @@ -0,0 +1,65 @@ +--- +slug: /next/guides/logging-queries +title: Logging Queries +description: You can log all the queries that are executed in Faust.js +--- + +In a development environment, you may want to log GraphQL queries that are being executed in your application. Faust.js provides a function, `logQueries`, to do this. + +`logQueries` is called within your `client/index.ts` file. Take the following `client/index.ts` example: + +```ts title="client/index.ts" {23-25} +/** + * GQTY: You can safely modify this file and Query Fetcher based on your needs + */ +import type { IncomingMessage } from 'http'; +import { getClient } from '@faustjs/next'; +import { + generatedSchema, + scalarsEnumsHash, + GeneratedSchema, + SchemaObjectTypes, + SchemaObjectTypesNames, +} from './schema.generated'; + +export const client = getClient< + GeneratedSchema, + SchemaObjectTypesNames, + SchemaObjectTypes +>({ + schema: generatedSchema, + scalarsEnumsHash, +}); + +if (process.env.NODE_ENV === 'development') { + logQueries(client); +} + +export function serverClient(req: IncomingMessage) { + return getClient({ + schema: generatedSchema, + scalarsEnumsHash, + context: req, + }); +} + +export * from './schema.generated'; +``` + +Note the conditional check for the node environment. It is recommended that you only log queries in a dev environment, and not in production. + +Additionally, the `logQueries` function returns a function than can be called to turn off the logger: + +```ts +if (process.env.NODE_ENV === 'development') { + const unsubscribe = logQueries(client); + + // queries are now logging + // ... + + unsubscribe(); + + // queries no longer log + // ... +} +``` diff --git a/internal/website/sidebars.js b/internal/website/sidebars.js index 0bb85063a..f424d7bf1 100644 --- a/internal/website/sidebars.js +++ b/internal/website/sidebars.js @@ -85,6 +85,11 @@ module.exports = { label: 'Authentication', id: 'next/guides/authentication', }, + { + type: 'doc', + label: 'Logging Queries', + id: 'next/guides/logging-queries', + }, { type: 'doc', label: '404s', From 1bf09e0d4623cb9326522b34194b66bc7a67c8d8 Mon Sep 17 00:00:00 2001 From: Blake Wilson Date: Fri, 5 Nov 2021 10:57:07 -0700 Subject: [PATCH 06/11] Fix docs site URLs --- docs/next/guides/fetching-data.mdx | 19 ++++++++++--------- docs/next/reference/expected-url-params.mdx | 2 +- docs/next/reference/hooks/hooks.mdx | 15 +++++++++++++++ docs/tutorial/querying-data.mdx | 6 +++--- internal/website/sidebars.js | 5 +++++ .../components/Features/HomepageFeatures.js | 2 +- packages/next/src/gqty/hooks/index.ts | 2 +- 7 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 docs/next/reference/hooks/hooks.mdx diff --git a/docs/next/guides/fetching-data.mdx b/docs/next/guides/fetching-data.mdx index 3798b436d..92f052140 100644 --- a/docs/next/guides/fetching-data.mdx +++ b/docs/next/guides/fetching-data.mdx @@ -127,11 +127,11 @@ This will ensure Faust.js uses the correct client to make requests on your behal ## Using the Client to Make Queries -Assuming you have created a client using the Faust.js `getClient` function, you will be able to take advantage of many of the added features that Faust.js provides, and also the general features provided by GQty. You can read our [hooks for fething data reference](../reference/custom-hooks) for examples on how to use some of the built-in hooks using the Faust.js client, but the client will support any query to your Headless WordPress API. Let's look at a few examples of how to use the client to make queries. +Assuming you have created a client using the Faust.js `getClient` function, you will be able to take advantage of many of the added features that Faust.js provides, and also the general features provided by GQty. You can read our [hooks for fetching data reference](../reference/hooks) for examples on how to use some of the built-in hooks using the Faust.js client, but the client will support any query to your Headless WordPress API. Let's look at a few examples of how to use the client to make queries. ### The useQuery Hook -If you are not able to use one of the [WordPress-specific hooks](../reference/custom-hooks) you can use the `useQuery` hook to make a query to the Headless WordPress API. This hook is useful for making any query supported by your Headless WordPress API. It essentially exposes your entire generated GQL schema to you for you to use what you need. For example, say you have a `Header` component and you want to fetch menu items from your "Primary" menu in WordPress. You could do so as follows: +If you are not able to use one of the [WordPress-specific hooks](../reference/hooks) you can use the `useQuery` hook to make a query to the Headless WordPress API. This hook is useful for making any query supported by your Headless WordPress API. It essentially exposes your entire generated GQL schema to you for you to use what you need. For example, say you have a `Header` component and you want to fetch menu items from your "Primary" menu in WordPress. You could do so as follows: ```tsx title=src/components/Header.tsx {4,12-15,30-36} import React from 'react'; @@ -222,7 +222,8 @@ export function PostForm() { content: content.value, }, }); - }}> + }} + >