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.
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-vuewhich 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
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!