More Mutations and Queries

In this section of the tutorial you’ll implement the voting feature! Authenticated users are allowed to submit a vote for a link. The most upvoted links will later be displayed on a separate route!

Preparing the Link component

Once more, let’s first prepare the app’s components before implementing the actual upvote mutation. There’s several things that the Link component isn’t currently displaying, compared to the real Hackernews site.

  • a link should display its number in the list of the current page (1., 2., …)
  • it should display an upvote button and the number of upvotes it received
  • it should display who posted the link
  • and it should display when it was posted

Before you’ll modify the Link component, let’s write a function that takes a timestamp and converts it to a string that’s more user friendly, e.g. "3 hours ago".

Now, let’s update the Link component with everything that is has previously been missing!

As you can see, we’ve also added a new prop. Each Link element will also render its position inside the list, so you have to now pass it the index prop from the LinkList component.

Notice that the app won’t run at the moment since the votes are not yet included in the query. You’ll fix that next!

All you do here is include information about the user who posted a link as well as information about each link’s votes in the query’s payload. You can now run the app again and the links will be ddisplayed properly.

Note: If you’re not able to fetch the links, restart the server and reload the browser. You could also check if everything is working as expected on GraphQL Playground!

The Upvote Mutation

Let’s now move on and implement the vote mutation!

When you’ve updated the Link component you also added an empty upvote handler. Let’s now add the mutation and populate that handler with the usual logic, like you did back for the Login component in a previous step.

This step should feel pretty familiar by now. You’re adding the new mutation inside of your component by adding the useMutation hook. You’re also passing the linkId variable to executeMutation, since it’s required by the VoteMutation’s definition.

You can now go ahead and test this! Run yarn start in hackernews-react-urql, make sure that you’re logged in, then click the upvote button on a link. You should then see the link’s upvote number update automagically!

Remember: We haven’t set up any configuration for @urql/exchange-graphcache yet, but since it’s a normalized cache, it knows that the link it receives back from the mutation needs to also be updated on the feed query!

Creating the Search page

Next up, you’ll add a search page to your app!

The search will be available under a new route and allow you to filter all links that have been submitted to your GraphQL API.

Again, this is a pretty standard setup. You’re rendering an input field where the user can type a search string.

It’s worth noting that this time we’d like to start the search imperatively. Instead of the useQuery hook starting the search immediately while the user is typing, we’d like to only start searching once the user clicks the “search” button.

For now the search handler and links array are also empty stubs, but we’ll be replacing them in a later step.

Let’s also add a button to the header so users can comfortably navigate to the search page.

You can now navigate to the search feature using the “search” button in the Header:

The Search Query

Great, let’s now go back to the Search component and implement the actual search!

This query looks similar to the feed query that’s used in LinkList. However, this time it takes in an argument called filter that will be used to constrain the list of links you want to retrieve.

Previously you’ve always just passed useQuery a query and some variables. But in the case of the new Search component, the query is meant to run programmatically, when the “search” button is clicked. You can utilise the executeQuery method and the pause argument to achieve this.

Like in LinkList you’re passing the query and variables arguments to useQuery. But instead of immediately running the query, the pause option is now set to true. This flag will cause useQuery to wait until executeQuery is programmatically called.

This is a very powerful option as you could also flip pause to false at any time to let the hook start the query automatically. This is essentially one of the use-cases of having executeQuery! You can call it programmatically to ask for new results or use it in combination with pause: true to make it behave like the useMutation hook’s executeMutation.

Go ahead and test the app by running yarn start in a terminal and navigating to http://localhost:3000/search. Then type a search string into the text field, submit the search, and verify that the links that are being displayed were filtered by your search string.

Unlock the next chapter
What does the 'pause' argument of urql's useQuery hook do?
It allows you to pause all ongoing queries
It allows you to update the query result manually
It pauses the query but it can still be triggered using 'executeQuery'
It pauses the query indefinitely