Using Vue’s Scoped Slots To Create GraphQL Data Components

In this quick example, I’ll show you how to create a GraphQL container component that can be used to “wrap” a presentation component and pass data to it as props. For this example, we’ll be creating some menus. In the below screenshot, the navigation menu and the sidebar menu both use the same GraphQL container to get the data, but they use completely different presentation components!

Note/Shameless plug: The data I’ll be using to get menu items is coming from a WordPress database. To setup the GraphQL schema and database connection I use a project that I’ve developed (and continue to develop) called WordExpressSchema. This tutorial won’t go into setting up the GraphQL server or the client — it will simply show you how to use scoped slots to work with really ANY GraphQL query.

But First — Why Is This a Good Idea?

There are several benefits to separating out the data-fetching component from the presentation component. Dan Abramov wrote what is probably considered the defining article on why this is a good idea. In short, separation makes each component more reusable, and they are easier to unit test.

The MenuQuery

For reference, here is what the GraphQL query looks like. I use Vue CLI with the webpack template and add a GraphQL loader so I keep all my queries in .gql files.

Again, its not really important what the query looks like, but for this example its helpful to understand the shape of the data.

The Sidebar Component

In the above screenshot, there is a sidebar that has a menu. Here’s what it looks like.

<menu-container> is the GraphQL component that we will create that actually fetches data. We pass in menuName as a prop (note in the above query there is a $menu variable — this is how we can get both the nav menu and the sidebar menu).

<sidebar-menu> is simply a presentation component that accepts a prop called menuItems , which is an array. We use a slot-scope of menu and then bind menuItems to menu.items. This will make a bit more sense when you see the menuContainer component, which is next!

Please note: the value of your slot-scope is a temporary variable — you can name it whatever you want (I decided to use menu because I thought it was the most semantically clear choice).

The MenuContainer Component

Note: This component is made possible by apollo-vue which is currently the most widely supported Apollo/GraphQL implementation available for Vue.

MenuContainer accepts a prop called menuName which is passed to the GraphQL query. I encourage you to read the Apollo Vue Query documentation to fully understand the setup, but know that basically this component fetches data in the shape of MenuQuery and makes menus data available to our template. We use menus (which is the data returned from the GraphQL query — our WordPress data) to then bind menuItems to the <slot> .

Effectively, the MenuContainer performs a GraphQL query and passes the resulting data into whatever child component uses the slot (in this case its SidebarMenu ). Now go forth and separate those concerns!

Ramsay is a full-stack JavaScript developer for a data analytics company in Springfield, VA. You can follow him on twitter or github. He likes when you do that.