{"id":438,"date":"2022-04-21T21:11:48","date_gmt":"2022-04-22T03:11:48","guid":{"rendered":"https:\/\/developers.wpengine.com\/blog\/?p=438"},"modified":"2023-06-15T13:53:43","modified_gmt":"2023-06-15T19:53:43","slug":"build-simple-headless-wordpress-app-react-wpgraphql","status":"publish","type":"post","link":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/","title":{"rendered":"Crash Course: Build a Simple Headless WordPress App with React &#038; WPGraphQL"},"content":{"rendered":"\n<p>In this tutorial, you will learn how to create a simple headless WordPress app using <a href=\"https:\/\/developers.wpengine.com\/docs\/glossary#react\">React<\/a> and <a href=\"https:\/\/developers.wpengine.com\/docs\/glossary#wpgraphql\">WPGraphQL<\/a>. This tutorial assumes a basic understanding of JavaScript, React fundamentals, GraphQL fundamentals, and WordPress. Using the prepared Code Sandbox repository will allow us to focus on points specific to React as a framework and <a href=\"https:\/\/www.apollographql.com\/docs\/react\/\">Apollo Client<\/a> for data fetching. By the end of this tutorial, you will be able to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use the GraphiQL IDE to compose GraphQL queries<\/li>\n\n\n\n<li>Use Apollo Client to fetch data in your app and render it to the page<\/li>\n\n\n\n<li>Use variables in GraphQL queries<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Build a Headless WordPress App with React and WPGraphQL\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/cdBBCCvIqvo?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Code Sandbox Overview<\/h2>\n\n\n\n<p>First, let\u2019s open up the Code Sandbox that we have prepared for this project. <a href=\"https:\/\/codesandbox.io\/s\/headless-wordpress-react-demo-starter-3sid45\">Here\u2019s the link!<\/a><\/p>\n\n\n\n<p>If you haven\u2019t used Code Sandbox previously, there are four sections on the screen. On the left, you can see the file structure of your project. Below are the dependencies that we\u2019ve already added to this project (<code>@apollo\/client<\/code> &amp; <code>graphql<\/code>). You can make changes to the files using the code editor in the middle and see your changes reflected in real-time in the embedded browser on the right.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png\" alt=\"\" class=\"wp-image-440\"\/><\/figure>\n\n\n\n<p>If at any point you encounter an unexpected error after you make changes, you can refresh the embedded browser, or even refresh the whole Code Sandbox page to get things working again. CodeSandbox will have saved your changes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">React App Overview<\/h2>\n\n\n\n<p>Before we start coding, let\u2019s take a look at the current state of this Code Sandbox application. In the embedded browser, it is displaying a page titled <code>Blog<\/code> that consists of many cards. Each card contains data for a blog post, including the post\u2019s title, date, author, and featured image, if it has one.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.15.34-PM-902x1024.png\" alt=\"\" class=\"wp-image-441\"\/><\/figure>\n\n\n\n<p>We can also click on each of these cards to view an individual post details page. This page includes much of the same information as on the card, and also contains the post\u2019s content. In the address bar of the embedded browser, we can also see that the URL changes to reflect the current page.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.16.17-PM-897x1024.png\" alt=\"\" class=\"wp-image-442\"\/><\/figure>\n\n\n\n<p>How are we making this happen? Open the <code>App.js<\/code> file in the Code Sandbox project. In this file, we are first importing <code>React<\/code> and some packages from <code>react-router-dom<\/code> to handle our routing. Then, we\u2019re importing two files &#8211; <code>HomePage<\/code> and <code>PostPage<\/code> &#8211; as well as some styles for our app.<\/p>\n\n\n\n<p>Inside of the <code>&lt;Switch&gt;<\/code> tag, the two <code>&lt;Route&gt;<\/code> tags are managing the routing. They check the path from the browser and render a certain component based on that path. As you change the URL while navigating the site, the component being displayed changes. This forms the basis of our navigation between the <code>HomePage<\/code> showing the list of all posts and the <code>PostPage<\/code> showing the individual post\u2019s details.<\/p>\n\n\n\n<p>Now, let\u2019s dive deeper into the <code>HomePage<\/code>. <code>\/pages\/HomePage.js<\/code>  looks like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">HomePage<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"page-container\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Blog<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostsList<\/span> \/&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><code>HomePage<\/code> renders a component called <code>PostsList<\/code>, which lives in <code>\/components\/PostsList.js<\/code> and looks like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> PostCard <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/PostCard\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { data } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/dummy-data\/posts\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">PostsList<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> loading = <span class=\"hljs-literal\">false<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> error = <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Loading posts...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Error :(<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> postsFound = <span class=\"hljs-built_in\">Boolean<\/span>(data?.posts.nodes.length);\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (!postsFound) {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>No matching posts found.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"posts-list\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      {data.posts.nodes.map((post) =&gt; (<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostCard<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{post.databaseId}<\/span> <span class=\"hljs-attr\">post<\/span>=<span class=\"hljs-string\">{post}<\/span> \/&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      ))}<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This is where the actual data fetching occurs to display the list of all posts on the <code>HomePage<\/code>. However, we are currently importing hard-coded JSON dummy data from the <code>\/dummy-data\/posts.js<\/code> file to populate this page. Your challenge is to remove this dummy data and fetch REAL data from a headless WordPress backend. This is where WPGraphQL and Apollo Client come in!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create an Apollo Client Instance<\/h2>\n\n\n\n<p>Let\u2019s get started with setting up our React app to fetch data from a WordPress backend! A number of GraphQL clients exist that you could use for this purpose. For our app, we&#8217;re going to use Apollo Client. Per Apollo Client&#8217;s <a href=\"https:\/\/www.apollographql.com\/docs\/react\/get-started\/\">Get Started documentation<\/a>, we first need to create an instance of Apollo Client.<\/p>\n\n\n\n<p>Inside the src directory, create a new folder called <code>lib<\/code>. Inside <code>lib<\/code>, create a file named <code>apollo.js<\/code>. Inside the newly created <code>\/lib\/apollo.js<\/code> file, add the following code:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { ApolloClient, InMemoryCache } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> client = <span class=\"hljs-keyword\">new<\/span> ApolloClient({\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">uri<\/span>: <span class=\"hljs-string\">' '<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">cache<\/span>: <span class=\"hljs-keyword\">new<\/span> InMemoryCache(),\n<\/span><\/span><span class='shcb-loc'><span>});\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> client;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The first line of code here imports <code>ApolloClient<\/code> and <code>InMemoryCache<\/code> from the <code>@apollo\/client<\/code> package. Then, below that, we create a new instance of <code>ApolloClient<\/code> and export that as a variable named <code>client<\/code>. When we create the new client, we pass in a configuration object with <code>uri<\/code> and <code>cache<\/code> properties.<\/p>\n\n\n\n<p>The <code>cache<\/code> property gets assigned to a new <code>InMemoryCache<\/code> instance. With this in place, the cache will &#8220;remember&#8221; the results of the GraphQL queries that get executed. If the same queries are requested again, Apollo Client will resolve the requests using the data in its cache rather than making a new network request every time. Read more about <a href=\"https:\/\/www.apollographql.com\/docs\/react\/caching\/overview\/\">Apollo Client&#8217;s caching capabilities here<\/a>.<\/p>\n\n\n\n<p>The <code>uri<\/code> property needs to point to the GraphQL endpoint we want to source our data from. The endpoint that we will be using for this tutorial is <a href=\"https:\/\/content.wpgraphql.com\/graphql\">https:\/\/content.wpgraphql.com\/graphql<\/a>. If you already have a WordPress server with an instance of WPGraphQL installed, you can use that instead, if you&#8217;d like. After adding this value to the <code>uri<\/code>, our file will look like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { ApolloClient, InMemoryCache } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> client = <span class=\"hljs-keyword\">new<\/span> ApolloClient({\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">uri<\/span>: <span class=\"hljs-string\">'https:\/\/content.wpgraphql.com\/graphql'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">cache<\/span>: <span class=\"hljs-keyword\">new<\/span> InMemoryCache(),\n<\/span><\/span><span class='shcb-loc'><span>});\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> client;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>With our client fully configured, the next step is to make it available anywhere in our application using the <code>ApolloProvider<\/code> component.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implement Apollo Provider Component<\/h2>\n\n\n\n<p>Apollo Client provides an <code>ApolloProvider<\/code> component that can be used to add the ApolloClient instance we created to <a href=\"https:\/\/reactjs.org\/docs\/context.html\">React context<\/a>. This will allow us to run GraphQL queries from anywhere within our app&#8217;s component tree.<\/p>\n\n\n\n<p>Inside of <code>App.js<\/code>, add the following import statements. These pull in the <code>client<\/code> we created in the previous step and the <code>ApolloProvider<\/code> component that Apollo Client provides. We will need both of these to make a connection.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { ApolloProvider } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\/react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> client <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/lib\/apollo\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, wrap the <code>&lt;Switch&gt;<\/code> component inside of an <code>&lt;ApolloProvider&gt;<\/code> component, passing the configured <code>client<\/code> as a prop:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ApolloProvider<\/span> <span class=\"hljs-attr\">client<\/span>=<span class=\"hljs-string\">{client}<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Switch<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Route<\/span> <span class=\"hljs-attr\">exact<\/span> <span class=\"hljs-attr\">path<\/span>=<span class=\"hljs-string\">\"\/\"<\/span> <span class=\"hljs-attr\">component<\/span>=<span class=\"hljs-string\">{HomePage}<\/span> \/&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Route<\/span> <span class=\"hljs-attr\">path<\/span>=<span class=\"hljs-string\">\"\/blog\/:slug\"<\/span> <span class=\"hljs-attr\">component<\/span>=<span class=\"hljs-string\">{PostPage}<\/span> \/&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Switch<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ApolloProvider<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"> }<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wrapping your app in an <code>ApolloProvider<\/code> gives you the ability to use the <a href=\"https:\/\/www.apollographql.com\/docs\/react\/api\/react\/hooks\/\">React hooks that Apollo Client provides<\/a>, such as <code>useQuery()<\/code>, from anywhere in your app.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Import <code>useQuery()<\/code> Hook in <code>PostsList<\/code><\/h2>\n\n\n\n<p>Now that we have a fully configured GraphQL client, we can start fetching some real data inside of our components. As mentioned previously, the <code>HomePage<\/code> component inside  <code>\/pages\/HomePage.js<\/code> renders the <code>PostsList<\/code> component to display the list of blog posts. Open up <code>\/components\/PostsList.js<\/code> in the editor so we can take a look at the PostsList component.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">PostsList<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">const<\/span> loading = <span class=\"hljs-literal\">false<\/span>;\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">const<\/span> error = <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Loading posts\u2026<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Error :(<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">const<\/span> postsFound = <span class=\"hljs-built_in\">Boolean<\/span>(data?.posts.nodes.length);\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">if<\/span> (!postsFound) {\n<\/span><\/span><span class='shcb-loc'><span>   <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>No matching posts found.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span> }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>   <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"posts-list\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">     {data.posts.nodes.map((post) =&gt; (<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostCard<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{post.databaseId}<\/span> <span class=\"hljs-attr\">post<\/span>=<span class=\"hljs-string\">{post}<\/span> \/&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     ))}<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">   <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"> );<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This <code>PostsList<\/code> component first includes checks for whether the data is loading, returned an error, or is empty. If none of these conditions are true, then the code <code>map<\/code>s over the array of data, passing rendering a <code>PostCard<\/code> component for each.<\/p>\n\n\n\n<p>For now, this component is pulling in placeholder dummy data. Let&#8217;s work toward populating it with dynamic data. First, let\u2019s import two things &#8211; <code>gql<\/code> and <code>useQuery<\/code> &#8211; at the top of our <code>\/components\/PostsList.js<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So now we&#8217;re set up to fetch data, but what does our GraphQL query need to look like? \ud83e\udd14 Let&#8217;s learn how to compose the GraphQL query we need using the GraphiQL IDE, next.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Compose GraphQL Query Using the GraphiQL IDE<\/h3>\n\n\n\n<p>To compose our GraphQL query, we&#8217;ll use a hosted instance of the <a href=\"https:\/\/github.com\/graphql\/graphiql\">GraphiQL<\/a> IDE that&#8217;s available at <a href=\"https:\/\/graphiql-online.com\/\">graphiql-online.com<\/a>. (Note the &#8220;i&#8221; in &#8220;GraphiQL&#8221;! It can easily be mistaken for the word &#8220;GraphQL&#8221; at first glance \ud83d\ude0a).<\/p>\n\n\n\n<p>Once you&#8217;ve opened <a href=\"https:\/\/graphiql-online.com\/\">graphiql-online.com<\/a> in a new browser tab, enter <a href=\"https:\/\/content.wpgraphql.com\/graphql\"><code>https:\/\/content.wpgraphql.com\/graphql<\/code><\/a> for the GraphQL endpoint and click the button to continue. Recall that this is the same endpoint that we configured Apollo Client to use inside of <code>\/lib\/apollo.js<\/code>.<\/p>\n\n\n\n<p>All of the data that exists in the GraphQL schema is shown in the <code>Explorer<\/code> section on the left. Developers can select boxes to indicate which data they would like to fetch, then GraphQL builds the query for them! Give it a try! Once you&#8217;ve checked a few boxes and composed a query, hit the play icon (\u25b6\ufe0f) to execute it and see the data that gets returned in the right-most pane.<\/p>\n\n\n\n<p>By looking at the data inside of <code>\/dummy-data\/posts.js<\/code>, we can see the shape of the data that our <code>PostsList<\/code> component expects. Using the GraphiQL Explorer, try to compose a query that looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-20-at-10.02.26-AM-1024x461.png\" alt=\"\" class=\"wp-image-447\"\/><\/figure>\n\n\n\n<p>Once you compose a query that&#8217;s returning the correct data, we can copy\/paste that query into our app.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Format Query with <code>gql<\/code><\/h3>\n\n\n\n<p>Back in the <code>PostsList<\/code> component, add this code underneath the <code>import<\/code> statements. Here, we pass the query we composed to a <code>gql<\/code> <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Template_literals#tagged_templates\">tagged template literal<\/a> (\u201cgql\u201d followed by two backticks) and assign the return value to a <code>GET_ALL_POSTS<\/code> variable.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> GET_ALL_POSTS = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  query getAllPosts {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    posts {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      nodes {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        databaseId<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        title<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        date<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        slug<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        author {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          node {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            name<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        featuredImage {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          node {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            altText<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            sourceUrl<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">`<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><code>gql<\/code> takes care of converting the query string into an <a href=\"https:\/\/en.wikipedia.org\/wiki\/Abstract_syntax_tree\">abstract syntax tree (AST)<\/a> object that Apollo Client can work with.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Fetch Data with the <code>useQuery()<\/code> Hook<\/h3>\n\n\n\n<p>Now let&#8217;s actually execute our GraphQL query. First, delete the dummy data import statement:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { data } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/dummy-data\/posts\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>&#8230;and also delete these variables from inside of the <code>export<\/code> statement in the <code>PostsList<\/code> component:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> loading = <span class=\"hljs-literal\">false<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> error = <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We will replace those variables with the destructed response that we get from <code>useQuery()<\/code>. Passing the <code>GET_ALL_POSTS<\/code> function into <code>useQuery()<\/code> will result in values for variables named <code>loading<\/code>, <code>error<\/code>, and <code>data<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_ALL_POSTS);\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Finally, our <code>HomePage<\/code> is dynamic! You should now be able to hit the refresh button on the embedded browser and see the &#8220;Loading posts&#8230;&#8221; message momentarily, then see the grid of posts appear.<\/p>\n\n\n\n<p>Congratulations! You are now successfully pulling data from a headless WordPress backend and rendering it out inside of a React app! \ud83c\udf89<\/p>\n\n\n\n<p>The final <code>PostsList.js<\/code> file should look like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> PostCard <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/PostCard\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> GET_ALL_POSTS = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  query getAllPosts {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    posts {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      nodes {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        databaseId<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        title<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        date<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        slug<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        author {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          node {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            name<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        featuredImage {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          node {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            altText<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">            sourceUrl<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">`<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">PostsList<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_ALL_POSTS);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Loading posts\u2026<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Error :(<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">const<\/span> postsFound = <span class=\"hljs-built_in\">Boolean<\/span>(data?.posts.nodes.length);\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">if<\/span> (!postsFound) {\n<\/span><\/span><span class='shcb-loc'><span>   <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>No matching posts found.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n<\/span><\/span><span class='shcb-loc'><span> }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>   <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"posts-list\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">     {data.posts.nodes.map((post) =&gt; (<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostCard<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{post.databaseId}<\/span> <span class=\"hljs-attr\">post<\/span>=<span class=\"hljs-string\">{post}<\/span> \/&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     ))}<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">   <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"> );<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the next section, we\u2019ll look at making similar changes to the <code>PostPage<\/code> file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Making <code>PostPage.js<\/code> Dynamic<\/h2>\n\n\n\n<p>In the last section, we focused on pulling multiple posts into the site home page using Apollo Client and WPGraphQL. This section will build on that example and look at how to create individual pages for each blog post, each with a unique URL.<\/p>\n\n\n\n<p>To begin, let\u2019s open the <code>\/pages\/PostPage.js<\/code> file and look at the existing code. It currently imports dummy data from <code>\/dummy-data\/post.js<\/code> and passes it into the <code>PostPageContent<\/code> component.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { Link } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react-router-dom\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> PostPageContent <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/PostPageContent\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { data } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/dummy-data\/post\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">PostPage<\/span>(<span class=\"hljs-params\">props<\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> loading = <span class=\"hljs-literal\">false<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> error = <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> postFound = <span class=\"hljs-literal\">true<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"page-container\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">to<\/span>=<span class=\"hljs-string\">\"\/\"<\/span>&gt;<\/span>\u2190 Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      {loading ? (<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Loading...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      ) : error ? (<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Error: {error.message}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      ) : !postFound ? (<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Post could not be found.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      ) : (<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostPageContent<\/span> <span class=\"hljs-attr\">post<\/span>=<span class=\"hljs-string\">{data.post}<\/span> \/&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      )}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  );<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As we did once before, let&#8217;s remove the dummy data and do some real data fetching instead.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Construct <code>GET_POST_BY_SLUG<\/code> Query<\/h3>\n\n\n\n<p>Back in the GraphiQL IDE, use the Explorer once more and select <code>post<\/code> from the list of schema objects. If you check the <code>id<\/code> and <code>idType<\/code> options, GraphiQL will help you begin to parameterize your query so that we can pass in variables. First, we can set the <code>idType<\/code> to <code>SLUG<\/code> from the dropdown in the Explorer. We want to use a dynamic variable for the slug so it can change every time we hit a new route. To accomplish this, we&#8217;ll have the query accept a <code>$id<\/code> variable with a required type of <code>ID<\/code>, like this: <code>getPostBySlug($id: ID!)<\/code>. Next, we&#8217;ll pass that value in as the <code>id<\/code>, like this: <code>post( id: $id, idType: SLUG )<\/code>. This tells GraphQL to use the value of <code>$id<\/code> to locate the blog post.<\/p>\n\n\n\n<p>Your query should then look like the one shown below. You can once again hit the play icon (\u25b6\ufe0f) to execute it and see the data that gets returned in the right-most pane.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-20-at-11.06.32-AM-1024x401.png\" alt=\"\" class=\"wp-image-450\"\/><\/figure>\n\n\n\n<p>As you can see, this query returned an error because there was no <code>id<\/code> value specified. We can fix this by passing in the slug from one of the posts that our <code>getAllPosts<\/code> query returned previously in the <code>Query Variables<\/code> pane at the bottom of the screen, like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-string\">\"query-any-page-by-its-path-using-wpgraphql\"<\/span>\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, if we press the play icon (\u25b6\ufe0f) again, the query should return the corresponding post details.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-20-at-11.02.59-AM-1024x400.png\" alt=\"\" class=\"wp-image-449\"\/><\/figure>\n\n\n\n<p>Once you verify that the query is correct, we will copy\/paste the query that you composed into your app.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Call <code>useQuery()<\/code> Hook from <code>PostPage.js<\/code><\/h3>\n\n\n\n<p>Now let&#8217;s execute our GraphQL query. Back in the <code>\/pages\/PostPage.js<\/code> file, delete the dummy data import statement:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { data } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/dummy-data\/post\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then, let\u2019s import two things: <code>gql<\/code> and <code>useQuery<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, add this code underneath the <code>import<\/code> statements. Here, we once again will pass the query we composed to <code>gql<\/code> and assign the return value to a <code>GET_POST_BY_SLUG<\/code> variable.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> GET_POST_BY_SLUG = gql`\n<\/span><\/span><span class='shcb-loc'><span>  query getPostBySlug($id: ID!) {\n<\/span><\/span><span class='shcb-loc'><span>    post(id: $id, idType: SLUG) {\n<\/span><\/span><span class='shcb-loc'><span>      title\n<\/span><\/span><span class='shcb-loc'><span>      date\n<\/span><\/span><span class='shcb-loc'><span>      content\n<\/span><\/span><span class='shcb-loc'><span>      categories {\n<\/span><\/span><span class='shcb-loc'><span>        nodes {\n<\/span><\/span><span class='shcb-loc'><span>          slug\n<\/span><\/span><span class='shcb-loc'><span>          name\n<\/span><\/span><span class='shcb-loc'><span>        }\n<\/span><\/span><span class='shcb-loc'><span>      }\n<\/span><\/span><span class='shcb-loc'><span>      author {\n<\/span><\/span><span class='shcb-loc'><span>        node {\n<\/span><\/span><span class='shcb-loc'><span>          name\n<\/span><\/span><span class='shcb-loc'><span>        }\n<\/span><\/span><span class='shcb-loc'><span>      }\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>`;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now that our query is set up in the application, we can use it throughout the rest of this page component.<\/p>\n\n\n\n<p>First, inside of the <code>export<\/code> statement in the <code>PostPage<\/code> component, delete these two lines:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> loading = <span class=\"hljs-literal\">false<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> error = <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We will replace those variables with the destructed response that we get from <code>useQuery()<\/code>. Passing the <code>GET_POST_BY_SLUG<\/code> function into <code>useQuery()<\/code> will result in values for variables named <code>loading<\/code>, <code>error<\/code>, and <code>data<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_POST_BY_SLUG);\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>However, we need to pass the slug into our <code>useQuery()<\/code> hook as a parameter.&nbsp; We can access the slug through the <code>props<\/code> value that is passed into the <code>PostPage<\/code> component at <code>props.match.params.slug<\/code> and send it through <code>useQuery()<\/code> as a specifically-formatted object. We can edit the code from the previous step to include this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_POST_BY_SLUG, {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attr\">variables<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-attr\">id<\/span>: props.match.params.slug\n<\/span><\/span><span class='shcb-loc'><span>\t}\n<\/span><\/span><span class='shcb-loc'><span>});\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Lastly, we also need to replace the <code>postFound<\/code> variable with a <code>Boolean<\/code> value indicating whether or not there is a <code>post<\/code> present inside of <code>data<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> postFound = <span class=\"hljs-built_in\">Boolean<\/span>(data?.post);\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>After making these changes, our final <code>\/pages\/PostsPage.js<\/code> file should look like this:<\/p>\n\n\n<pre class=\"wp-block-code language-jsx\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { Link } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react-router-dom\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> PostPageContent <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/PostPageContent\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { gql, useQuery } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> GET_POST_BY_SLUG = gql<span class=\"hljs-string\">`<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  query getPostBySlug($id: ID!) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    post(id: $id, idType: SLUG) {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      title<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      date<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      content<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      categories {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        nodes {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          slug<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          name<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      author {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        node {<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">          name<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">        }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">      }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">    }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">  }<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-string\">`<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">PostPage<\/span>(<span class=\"hljs-params\">props<\/span>) <\/span>{\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_POST_BY_SLUG, {\n<\/span><\/span><span class='shcb-loc'><span>\t<span class=\"hljs-attr\">variables<\/span>: {\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-attr\">id<\/span>: props.match.params.slug\n<\/span><\/span><span class='shcb-loc'><span>\t}\n<\/span><\/span><span class='shcb-loc'><span>});\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">const<\/span> postFound = <span class=\"hljs-built_in\">Boolean<\/span>(data?.post);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span> <span class=\"hljs-keyword\">return<\/span> (\n<\/span><\/span><span class='shcb-loc'><span>   <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"page-container\"<\/span>&gt;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\">     <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Link<\/span> <span class=\"hljs-attr\">to<\/span>=<span class=\"hljs-string\">\"\/\"<\/span>&gt;<\/span>\u2190 Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Link<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     {loading ? (<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Loading\u2026<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     ) : error ? (<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Error: {error.message}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     ) : !postFound ? (<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Post could not be found.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     ) : (<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostPageContent<\/span> <span class=\"hljs-attr\">post<\/span>=<span class=\"hljs-string\">{data.post}<\/span> \/&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">     )}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">   <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"> );<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"xml\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">}<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Done! \ud83c\udf89<\/h2>\n\n\n\n<p>You should now be able to navigate back and forth between the homepage, which shows the list of posts, and the single post pages.<\/p>\n\n\n\n<p>Congratulations on creating a headless WordPress site! Thanks to your hard work, the app is now leveraging Apollo Client and WPGraphQL to pull data from a real headless WordPress backend and use it to render your pages!<\/p>\n\n\n\n<p>We covered a lot of ground in this crash course. Hopefully, you now have a good understanding of how you can leverage tools like React and WPGraphQL to build headless WordPress sites.<\/p>\n\n\n\n<p>Thanks for following along!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you will learn how to create a simple headless WordPress app using React and WPGraphQL. This tutorial assumes a basic understanding of JavaScript, React fundamentals, GraphQL fundamentals, [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_EventAllDay":false,"_EventTimezone":"","_EventStartDate":"","_EventEndDate":"","_EventStartDateUTC":"","_EventEndDateUTC":"","_EventShowMap":false,"_EventShowMapLink":false,"_EventURL":"","_EventCost":"","_EventCostDescription":"","_EventCurrencySymbol":"","_EventCurrencyCode":"","_EventCurrencyPosition":"","_EventDateTimeSeparator":"","_EventTimeRangeSeparator":"","_EventOrganizerID":[],"_EventVenueID":[],"_OrganizerEmail":"","_OrganizerPhone":"","_OrganizerWebsite":"","_VenueAddress":"","_VenueCity":"","_VenueCountry":"","_VenueProvince":"","_VenueState":"","_VenueZip":"","_VenuePhone":"","_VenueURL":"","_VenueStateProvince":"","_VenueLat":"","_VenueLng":"","_VenueShowMap":false,"_VenueShowMapLink":false,"footnotes":""},"categories":[23],"tags":[],"class_list":["post-438","post","type-post","status-publish","format-standard","hentry","category-headless"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Crash Course: Build a Simple Headless WordPress App with React &amp; WPGraphQL - Builders<\/title>\n<meta name=\"description\" content=\"Build a simple headless WordPress app with React &amp; WPGraphQL! You&#039;ll learn how to pull data out of WordPress using GraphQL and render it in your app.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Crash Course: Build a Simple Headless WordPress App with React &amp; WPGraphQL - Builders\" \/>\n<meta property=\"og:description\" content=\"Build a simple headless WordPress app with React &amp; WPGraphQL! You&#039;ll learn how to pull data out of WordPress using GraphQL and render it in your app.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/\" \/>\n<meta property=\"og:site_name\" content=\"Builders\" \/>\n<meta property=\"article:published_time\" content=\"2022-04-22T03:11:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-15T19:53:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png\" \/>\n<meta name=\"author\" content=\"Grace Erixon\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:site\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Grace Erixon\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/\"},\"author\":{\"name\":\"Grace Erixon\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/238dfb380aff5f2c58b8572d0b661deb\"},\"headline\":\"Crash Course: Build a Simple Headless WordPress App with React &#038; WPGraphQL\",\"datePublished\":\"2022-04-22T03:11:48+00:00\",\"dateModified\":\"2023-06-15T19:53:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/\"},\"wordCount\":2097,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png\",\"articleSection\":[\"Headless\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/\",\"name\":\"Crash Course: Build a Simple Headless WordPress App with React & WPGraphQL - Builders\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png\",\"datePublished\":\"2022-04-22T03:11:48+00:00\",\"dateModified\":\"2023-06-15T19:53:43+00:00\",\"description\":\"Build a simple headless WordPress app with React & WPGraphQL! You'll learn how to pull data out of WordPress using GraphQL and render it in your app.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#primaryimage\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/build-simple-headless-wordpress-app-react-wpgraphql\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Crash Course: Build a Simple Headless WordPress App with React &#038; WPGraphQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"name\":\"Builders\",\"description\":\"Reimagining the way we build with WordPress.\",\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\",\"name\":\"WP Engine\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"width\":348,\"height\":68,\"caption\":\"WP Engine\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/wpebuilders\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCh1WuL54XFb9ZI6m6goFv1g\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/238dfb380aff5f2c58b8572d0b661deb\",\"name\":\"Grace Erixon\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g\",\"caption\":\"Grace Erixon\"},\"description\":\"Grace Erixon is a Developer Advocate at WP Engine. She has been developing with headless WordPress since 2021. Connect with her on the Headless WordPress Discord community, Twitter, or LinkedIn.\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/author\\\/grace-erixonwpengine-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Crash Course: Build a Simple Headless WordPress App with React & WPGraphQL - Builders","description":"Build a simple headless WordPress app with React & WPGraphQL! You'll learn how to pull data out of WordPress using GraphQL and render it in your app.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/","og_locale":"en_US","og_type":"article","og_title":"Crash Course: Build a Simple Headless WordPress App with React & WPGraphQL - Builders","og_description":"Build a simple headless WordPress app with React & WPGraphQL! You'll learn how to pull data out of WordPress using GraphQL and render it in your app.","og_url":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/","og_site_name":"Builders","article_published_time":"2022-04-22T03:11:48+00:00","article_modified_time":"2023-06-15T19:53:43+00:00","og_image":[{"url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png","type":"","width":"","height":""}],"author":"Grace Erixon","twitter_card":"summary_large_image","twitter_creator":"@wpebuilders","twitter_site":"@wpebuilders","twitter_misc":{"Written by":"Grace Erixon","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#article","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/"},"author":{"name":"Grace Erixon","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/238dfb380aff5f2c58b8572d0b661deb"},"headline":"Crash Course: Build a Simple Headless WordPress App with React &#038; WPGraphQL","datePublished":"2022-04-22T03:11:48+00:00","dateModified":"2023-06-15T19:53:43+00:00","mainEntityOfPage":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/"},"wordCount":2097,"commentCount":0,"publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"image":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png","articleSection":["Headless"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/","url":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/","name":"Crash Course: Build a Simple Headless WordPress App with React & WPGraphQL - Builders","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#primaryimage"},"image":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#primaryimage"},"thumbnailUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png","datePublished":"2022-04-22T03:11:48+00:00","dateModified":"2023-06-15T19:53:43+00:00","description":"Build a simple headless WordPress app with React & WPGraphQL! You'll learn how to pull data out of WordPress using GraphQL and render it in your app.","breadcrumb":{"@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#primaryimage","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2022\/04\/Screen-Shot-2022-04-19-at-5.13.04-PM-1024x530.png"},{"@type":"BreadcrumbList","@id":"https:\/\/wpengine.com\/builders\/build-simple-headless-wordpress-app-react-wpgraphql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wpengine.com\/builders\/"},{"@type":"ListItem","position":2,"name":"Crash Course: Build a Simple Headless WordPress App with React &#038; WPGraphQL"}]},{"@type":"WebSite","@id":"https:\/\/wpengine.com\/builders\/#website","url":"https:\/\/wpengine.com\/builders\/","name":"Builders","description":"Reimagining the way we build with WordPress.","publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wpengine.com\/builders\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/wpengine.com\/builders\/#organization","name":"WP Engine","url":"https:\/\/wpengine.com\/builders\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","width":348,"height":68,"caption":"WP Engine"},"image":{"@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/wpebuilders","https:\/\/www.youtube.com\/channel\/UCh1WuL54XFb9ZI6m6goFv1g"]},{"@type":"Person","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/238dfb380aff5f2c58b8572d0b661deb","name":"Grace Erixon","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/85b32abfcbc7a3028fc8a4d3f0f299333783fc24197648f25e75661c9e1a8a97?s=96&d=mm&r=g","caption":"Grace Erixon"},"description":"Grace Erixon is a Developer Advocate at WP Engine. She has been developing with headless WordPress since 2021. Connect with her on the Headless WordPress Discord community, Twitter, or LinkedIn.","url":"https:\/\/wpengine.com\/builders\/author\/grace-erixonwpengine-com\/"}]}},"_links":{"self":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/comments?post=438"}],"version-history":[{"count":0,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/438\/revisions"}],"wp:attachment":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/media?parent=438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/categories?post=438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/tags?post=438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}