From c719d7c861404014592837015bb2e3d3f6aefc09 Mon Sep 17 00:00:00 2001 From: Blake Wilson Date: Fri, 5 Nov 2021 09:29:43 -0700 Subject: [PATCH] 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

- - - ); -} -``` - -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

- - - ); -} -``` - -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],