Adding local filesystem data

In the previous section, you saw how to get a basic Gatsby website up and running. This website wasn't very interesting because there was no data to drive it. For example, the data that drives a blog is the blog entry content stored in a database—the blog framework that renders the post lists and posts themselves use this data to render markup.

You can do the same thing with Gatsby but in a more sophisticated way. First, the markup (or in this case, React components) is statically built and bundled once. These builds are then served to users without having to query a database or API. Second, the plugin architecture used by Gatsby means that you're not restricted to only one source of data and that different sources are often combined. Lastly, GraphQL is the querying abstraction that sits on top of all of these things and delivers data to your React components.

To get started, you need a data source to drive the content of your website. We'll keep things simple for now and use a local JSON file as the source. To do so, you need to install the gatsby-source-filesystem plugin:

npm install --save gatsby-source-filesystem

Once this package is installed, you can add it to your project by editing your gatsby-config.js file:

plugins: [ 
  // Other plugins... 
  { 
    resolve: 'gatsby-source-filesystem', 
    options: { 
      name: 'data', 
      path: '${__dirname}/src/data/', 
    }, 
  }, 
] 

The name option tells the GraphQL backend how to organize the query result. In this case, everything will be under a data property. The path option restricts which files are readable. The path used in this example is src/data—feel free to throw a file into that directory so that it's queryable.

At this point, you can go ahead and start up the Gatsby development server. The GraphiQL utility is accessible at http://localhost:8000/___graphql. When developing Gatsby websites, you will utilize this tool often as it allows you to create ad hoc GraphQL queries and execute them on the fly. When you first load this interface, you'll see something like this:

The left panel is where you write your GraphQL queries, clicking on the Play button above executes the query, and the panel to the right displays the query results. The docs link in the top-right is a useful way to explore the available GraphQL types that Gatsby creates for you. Additionally, the query editor pane to the right will autocomplete as you type to help make building queries easier.

Let's execute your first query that lists information about files on the filesystem. Remember that you need at least one file in src/data in order to have your query return any results. Here is how to query the name, extension, and the size of files in your data directory:

As you can see, specific node fields are specified in the query. The result in the right panel shows that you get the exact fields that you ask for. Part of GraphQLs appeal is that you can create arbitrarily nested and complex queries that span multiple backend data sources. However, delving into the specifics of GraphQL go way beyond the scope of this book. The Gatsby home page (https://www.gatsbyjs.org/) has some great resources on GraphQL, including links to other GraphQL tutorials and documentation.

The takeaway here is that the gatsby-source-filesystem data source plugin did all of the heavy GraphQL lifting for you. It generates the entire schema for you, which means that once you have the plugin installed, you can start the development server and experiment with autocomplete and documentation right away.

Moving forward with the example, you probably don't have any need to render local file data in your UI. So let's create a articles.json file that has some JSON content:

[ 
  { "topic": "global", "title": "Global Article 1" }, 
  { "topic": "global", "title": "Global Article 2" }, 
  { "topic": "local", "title": "Local Article 1" }, 
  { "topic": "local", "title": "Local Article 2" }, 
  { "topic": "sports", "title": "Sports Article 1" }, 
  { "topic": "sports", "title": "Sports Article 2" } 
]

This JSON structure is an array of article objects with topic and title properties. This is the data that you want to query with GraphQL. To do so, you need to install another Gatsby plugin:

npm install --save gatsby-transformer-json

The gatsby-transformer-json plugin is from another category of Gatsby plugins—transformers. Source plugins are responsible from feeding data into Gatsby, while transformers are responsible for making the data queryable via GraphQL. Just like any plugin you want to use, you need to add it to your project config:

plugins: [ 
  // Other plugins... 
  'gatsby-transformer-json', 
], 

Now that you have a file with JSON content in your data directory and the gatsby-transformer-json plugin installed and enabled, you can go back to GraphiQL and query for JSON content:

The gatsby-transformer-json plugin makes the allArticlesJson query possible because it defines the GraphQL schema for you, based on the JSON data found in the data source. Under node, you can ask for specific properties, as you would with any other GraphQL query. In the results, you get all of the JSON data that your query asked for.

In this example, let's assume that you want three separate pages for listing articles, organized by topic. You need a way to filter the nodes that are returned by the query. You can add filters directly into your GraphQL syntax. For example, to find only global articles, you do execute the following query:

This time a filter argument is passed to the allArticlesJson query. Here, the query is asking for nodes with a topic value of global. Sure enough, the articles with a global topic are returned in the result.

The GraphiQL utility allows you to design a GraphQL query that can then be used by your React component. Once you have a query that's returning the correct results, you can simply copy it into your component. This last query returns global articles, so you can use it with the component used for the pages/global.js page:

import React from 'react' 
import Link from 'gatsby-link' 
 
export default ({ data: { allArticlesJson: { edges } } }) => ( 
  <div>
<h1>Global Articles</h1> <Link to="/">Home</Link> <ul> {edges.map(({ node: { title } }) => ( <li key={title}>{title}</li> ))} </ul> </div> ) export const query = graphql' query GlobalArticles { allArticlesJson(filter: { topic: { eq: "global" } }) { edges { node { topic title } } } }
'

There are two things to pay attention to in this module. First, look at the argument passed to the component and notice how it matches the result data that you saw in GraphiQL. This data is then used to render the list of global article titles. Next, notice the query export string. During build time, Gatsby will find this string and execute the appropriate GraphQL query so that your component has a static snapshot of the results.

Given that you now know how to filter for global articles, you can now update the filter for the pages/local.js page:

import React from 'react' 
import Link from 'gatsby-link' 
 
export default ({ data: { allArticlesJson: { edges } } }) => ( 
  <div> 
    <h1>Local Articles</h1> 
    <Link to="/">Home</Link> 
    <ul> 
      {edges.map(({ node: { title } }) => ( 
        <li key={title}>{title}</li> 
      ))} 
    </ul> 
  </div> 
)
export const query = graphql' query LocalArticles { allArticlesJson(filter: { topic: { eq: "local" } }) { edges { node { topic title } } } } '

And here's what the pages/sports.js page looks like:

import React from 'react' 
import Link from 'gatsby-link' 
 
export default ({ data: { allArticlesJson: { edges } } }) => ( 
  <div> 
    <h1>Sports Articles</h1> 
    <Link to="/">Home</Link> 
    <ul> 
      {edges.map(({ node: { title } }) => ( 
        <li key={title}>{title}</li> 
      ))} 
    </ul> 
  </div> 
) 
 
export const query = graphql' 
  query SportsArticles { 
    allArticlesJson(filter: { topic: { eq: "sports" } }) { 
      edges { 
        node { 
          topic 
          title 
        } 
      } 
    } 
  } 
' 

You might have noticed that these three components look very similar. This is because they're all working with the same data. The only unique thing about them is their title. To reduce some of this redundancy, you could create a higher-order component that takes a name argument and returns the same underlying component used on each page:

import React from 'react' 
import Link from 'gatsby-link' 
 
export default title => ({ data: { allArticlesJson: { edges } } }) => ( 
  <div> 
    <h1>{title}</h1> 
    <Link to="/">Home</Link> 
    <ul> 
      {edges.map(({ node: { title } }) => ( 
        <li key={title}>{title}</li> 
      ))} 
    </ul> 
  </div> 
) 

Then, you could use it like this:

import React from 'react' 
Import ArticleList from '../components/ArticleList' 
 
export default ArticleList('Global Articles') 
 
export const query = graphql' 
  query GlobalArticles { 
    allArticlesJson(filter: { topic: { eq: "global" } }) { 
      edges { 
        node { 
          topic 
          title 
        } 
      } 
    } 
  } 
'

In order to view all of these pages, you need an index page that links to each of them:

import React from 'react' 
import Link from 'gatsby-link' 
 
const IndexPage = () => ( 
  <div> 
    <h1>Home</h1> 
    <p>Choose an article category</p> 
    <ul> 
      <li> 
        <Link to="/global/">Global</Link> 
      </li>
<li> <Link to="/local/">Local</Link> </li>

<li> <Link to="/sports/">Sports</Link> </li> </ul> </div> ) export default IndexPage

Here's what the home page looks like:

If you were to click on one of the topic links, like Global for example, you're taken to an article list page:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.2.122