Skip to content

Commit

Permalink
Update creating-dynamically-rendered-navigation.md (gatsbyjs#7823)
Browse files Browse the repository at this point in the history
* Update creating-dynamically-rendered-navigation.md

Hopefully this is what you guys were thinking, if not I can re-write it! :)

* Update creating-dynamically-rendered-navigation.md

* Add Gatsby cli starter

* Remove unnecessary GraphQL, trim down content.

* Small tweaks

* Added diffs, some minor changes.

* Added back ticks to some properties

* Remove extra has

* Remove redundant sentence

* Added link to GraphQL website

* Added where to next section

Linked the two following documentation pages under "Building apps with Gatsby"

* Added backticks to all menuLinks

* Fix grammatical errors

Fix as many grammatical errors as I could find.

* Update and rename creating-dynamically-rendered-navigation.md to Centralizing your site's navigation.md

* Create Rendering sidebar navigation dynamically.md

* hyphenated file name
  • Loading branch information
outofthisworld authored and shannonbux committed Sep 13, 2018
1 parent 472af8d commit 160747f
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 8 deletions.
3 changes: 3 additions & 0 deletions docs/docs/Rendering sidebar navigation dynamically.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
title: Rendering sidebar navigation dynamically
---
263 changes: 263 additions & 0 deletions docs/docs/centralizing-your-sites-navigation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
---
title: Centralizing your site's navigation
---


## Creating dynamic navigation in Gatsby

At times you will want to be able to edit your website's navigation in response to a *change in requirements*. To achieve this, you can use Gatsby to dynamically generate your navigation. Where you store the data for your navigation can be anywhere - a backend API, CMS, headless CMS or even the filesystem.

What this section will cover:

- Adding data to your site's configuration
- Querying the data using GraphQL
- Pulling the data into a component using StaticQuery
- Dynamically rendering your navigation

You will be using `gatsby-config.js` to store the data for your links. `gatsby-config.js` is a file used for configuring Gatsby, located in the root path of every Gatsby project. A plain old javascript object is exported from this file; this object contains the `siteMetadata` object which you can query through graphql when generating your static pages.

This guide will use the Gatsby starter project `gatsby-starter-default`, which can be downloaded through the Gatsby command line interface tool using the command `gatsby new [project-name] https://github.com/gatsbyjs/gatsby-starter-default#v2`.

### Creating the link data
First, locate the `gatsby-config.js` file in the root directory of your project. Inside the `siteMetadata` object, add an array of menu link objects. These objects should contain two properties: `name` and `link`. `name` is the name of your navigation item and `link` is the page which will be navigated to when a menu item is clicked.

```diff
module.exports = {
siteMetadata: {
title: 'Gatsby Default Starter',
+ menuLinks:[
+ {
+ name:'home',
+ link:'/'
+ },
+ {
+ name:'page2',
+ link:'/page-2'
+ }
+ ]
},
plugins: []
}
```
### Viewing the `siteMetadata` in GraphQL

GraphQL can be used to query for information contained in the `siteMetadata` object located in your project's `gatsby-config.js`. In order to test this out you can start the `default-starter-project` in development mode by running `npm run develop`.

Navigate to `http://localhost:8000/___graphql` in your browser to view the GraphiQL editor, which enables you to test GraphQL queries on the underlying APIs. Using the documentation explorer you can view the current GraphQL schema for your project, which is an invaluable resource during development.

Examining the available types in GraphQL you will notice that you can query `site`. This GraphQL type further returns the `siteMetadata` which needs to be accessed to create the dynamic navigation. At this point it is useful if you know a little GraphQL in order to extract the menu links. If you are unfamiliar with GraphQL, there is some excellent documentation available at GraphQL's official website found [here](https://graphql.org/learn/) tha you can use to brush up on your skills! The query below will return the menu links.

```js
query SiteQuery {
site {
siteMetadata {
title
menuLinks {
name
link
}
}
}
}
```

When executing this query within the GraphiQL editor you see output that looks similar to the following:

```js
{
"data": {
"site": {
"siteMetadata": {
"title": "Gatsby Default Starter",
"menuLinks": [
{
"name": "home",
"link": "/"
},
{
"name": "page2",
"link": "/page-2"
}
]
}
}
}
}
```

Perfect! You now have a way of obtaining data from the `gatsby-config.js` file. Let's continue by pulling this data into the layout using the query you just formed.

### Pulling data inside the layout component

Inside your project, locate the `src/components` folder and navigate to the `layout.js` file. Within this layout component you should notice a component named `StaticQuery`.

StaticQuery is a new component introduced in Gatsby V2, which allows you to run GraphQL queries within your components, not just pages. It allows developers to colocate data with their components.

Let's extend the query within this component to include the menu links, so it looks like so:

```diff
const Layout = ({ children }) => (
<StaticQuery
query={graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
+ menuLinks {
+ name
+ link
+ }
}
}
}
`}
render={data => (
<React.Fragment>
<Helmet
title={'tite'}
meta={[
{ name: 'description', content: 'Sample' },
{ name: 'keywords', content: 'sample, something' },
]}
>
</Helmet>
<Header siteTitle={data.site.siteMetadata.title} />
<div
style={{
margin: '0 auto',
maxWidth: 960,
padding: '0px 1.0875rem 1.45rem',
paddingTop: 0,
}}
>
{children}
</div>
</React.Fragment>
)}
/>
)
```

With the above changes to your `StaticQuery` component, the `render` property, which accepts a function that takes one argument, now has access to the menu links for use inside the function (as the argument). The last thing that is left to do is to display the site's navigation.

To do this, the header component that is already available in the project seems like it might be a good starting place to display the navigation. Lets pass the `menuLinks` object to this header component like so:
```diff
const Layout = ({ children }) => (
<StaticQuery
query={graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
+ menuLinks {
+ name
+ link
+ }
}
}
}
`}
render={data => (
<React.Fragment>
<Helmet
title={'tite'}
meta={[
{ name: 'description', content: 'Sample' },
{ name: 'keywords', content: 'sample, something' },
]}
>
</Helmet>
- <Header siteTitle={data.site.siteMetadata.title} />
+ <Header menuLinks={data.site.siteMetadata.menuLinks} siteTitle={data.site.siteMetadata.title}/>
<div
style={{
margin: '0 auto',
maxWidth: 960,
padding: '0px 1.0875rem 1.45rem',
paddingTop: 0,
}}
>
{children}
</div>
</React.Fragment>
)}
/>
)
```

### Using the header component to display the navigation

Locate the `header.js` file inside `src/components` and remove everything so only the functional component definition is left (everything else is just boilerplate code given to us when generating our project):

```diff
import React from 'react'
import { Link } from 'gatsby'
const Header = ({ siteTitle, menuLinks }) => (
- <div
- style={{
- background: 'rebeccapurple',
- marginBottom: '1.45rem',
- }}
- >
- <div
- style={{
- margin: '0 auto',
- maxWidth: 960,
- padding: '1.45rem 1.0875rem',
- }}
- >
- <div style={{
- display: 'flex',
- 'justifyItems': 'space-between',
- 'alignItems': 'center'
- }}>
- <h1 style={{ margin: 0, flex: 1 }}>
- <Link
- to="/"
- style={{
- color: 'white',
- textDecoration: 'none',
- }}
- >
- {siteTitle}
- </Link>
- </h1>
-
- </div>
- </div>
- </div>
)
```

The `siteTitle` and `menuLinks` arguments are de-structered es6 syntax for quickly accessing an objects inner properties. It is functionally equivalent to writing `object.siteTitle` or `object.menuLinks`.

You can now access the header component's props and map the `menuLinks` array into elements that can be rendered in the document:

```diff
import React from 'react'
import { Link } from 'gatsby'

const Header = ({ siteTitle, menuLinks }) => (
+ <nav style={{ display: 'flex', flex: 1 }}>
+ {
+ menuLinks.map(link =>
+ <li key={link.name} style={{ 'listStyleType': 'none' }}>
+ <Link to={link.link}>{link.name}</Link>
+ </li>)
+ }
+ </nav>
)
```

Starting the development server by running `npm run develop` and navigating to `http://localhost:8000` you should now see some dynamically genrated menu links on your page.

If you have made it this far, good job! You can now add new site links to your website dynamically by adding entries to the `gatsby-config.js` file.

## Where to next?
Be sure to check out more documentation for further in-depth examples and guides on achieving tasks using Gatsby.

- [Authentication in Gatsby](https://next.gatsbyjs.org/docs/authentication/)
- [E-commerce in Gatsby](https://next.gatsbyjs.org/docs/e-commerce/)



8 changes: 0 additions & 8 deletions docs/docs/creating-dynamically-rendered-navigation.md

This file was deleted.

0 comments on commit 160747f

Please sign in to comment.