Creating the Product List
A product list is the most common element found on any online shop/marketplace regardless of how it’s built, but it is also the hardest element to create without some flaws. There are serious guidelines that a developer must follow or the performance of a very common component, that may appear multiple times on one page, could tank your application’s speed and UX.
What are the guidelines?
- Never query all your products at once, use pagination instead. Specifically, cursor-based pagination, it’s following the principles of setting some filters on what type of products you want and what order they are and ignoring everything else. We don’t care how many products there are in total because with could take a long time to count them. Just continue to send enough to feel the view as a user browses the list. If the user wants a specific product from the list allow the user to update the filters to be more specific and refresh the products with the new filters.
- Only query the data you need when you need it. This means only query the data you need to display on the product list. Typically this is the “title”, “short description”, “price”, and the “thumbnail”. You’ll also need the “id” and “productId” for caching or an “Add to cart” button, but that’s just about it. No need to get all the product information for the product page when the user might not even view that product.
Before we begin.
We are going to skip setting up a React/Apollo application because there are a ton of great tutorials on the web as well as the Apollo Docs. Instead, we will do three simple steps to prepare.
- Make a list of the NPM dependencies we will require for reference.
- react
- react-dom
- @apollo/client
- html-react-parser
- graphql
- styled-components
- lodash
- prop-types
- Make a quick note of the project “src” structure
- assets/ – Will contain non-js project files like fonts or images,
- components/ – Will contain reusable components
- app.js – Application root, we will be staging our product list component for testing with the Webpack “devServer” here.
- grid.js – Simple reusable style-component.
- products/ – Will contain our product list component files
- index.js – Application entry, we will set up our “ApolloClient” and render our “App” wrapped in an “ApolloProvider” here.
- Create our index.js, components/app.jsx, components/grid.js files
Nothing to complex here if you have basic familiarity with React and Apollo.
A quick, versatile, and reusable Grid styled component.
We are just importing our <ProductsList />
component and rendering it.
Creating the component.
Now start the development server based on how you set up your application and React should throw a compile error because ./products/index.js
doesn’t exist yet. So let’s jump right into developing our simple-in-design and reusable product list component. It will be made up of two components, a list component for rendering items and the controls for filtering them, and an item component for defining who the individual product data should be rendered. So let’s start with components/products/index.jsx
.
This is our list component. It’ll do the job of querying our products and mapping our product data to the list of <ProductsItem>
components, however, if you stick this in the application and use it you get an error because components/products/item.jsx
doesn’t exist so let’s make that too.
This is our item component. Right now, it just displays the most basic product data, simple enough. It’ll do much more later in the tutorial, but this will do for now.
If you run an application now you should see a list of 10 products. If you don’t see any product check your browser console for error messages, and follow accordingly. If you don’t see any because there is no product in store, I suggest importing the sample product data included in the WooCommerce plugin while developing[2].
Adding some pagination
Well, this is fine all we ever plan to sell is 10 items, but since that’s probably not the case let’s implement some pagination. First, we’ll tell Apollo’s cache how to merge the next request’s response with the last response using type policies by making some changes to /index.js
.
relayStylePagination()
is a merge function created designed to work on fields implementing the relay specification and it works for the most part, but I’ve noticed it doesn’t work with the nodes
field and only merges the edges
field.
Now we’ll create a callback for executing the “fetchMore” request. This will tell Apollo to grab the next group of products and add them to the “data” object essentially. To do this, we’ll have to make some changes to products/index.jsx
This implements a loadMore callback that is executed when the <InfinteLoader />
is scrolled passed. This callback queries the next set of products and updates the GET_PRODUCTS
query results that are stored in Apollo’s cache. These new products are this added to the data
object in ProductsList
component.
This implementation of allows for controlling the number of products queried at one time by setting the first
or last
props on the ProductsList
And there you have it. A product list with pagination. Next, we’ll be implementing a product page with a heavy focus on what each piece of data provided by the GraphQL Interface type Product
, and how that data should be used.
Quick Tip
You can actually implement some complex filtering capabilities by making some small changes to the GET_PRODUCTS
query
With these changes it’s now possible to filtering using the
where
prop.
To what properties are available on the GraphQL Input type
RootQueryToProductConnectionWhereArgs
. You can search this type and more using the Docs panel on the right side of Playground.