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!
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.
1.
, 2.
, …)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
!
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 automatically!
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!
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
:
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.