3.2 - Nyt Results
Creating our Component
We need to set up a component, create a file called, NytResults.js
to display our results!!! Since we've handled all of the "smarts" of the applications in our parent component, we can make this a functional component. The purpose of this component is to take the results and nicely render them. Let's start our component.
By passing props
in the parentheses of our component, we can now access the props in our component, which we'll need because we're going to need to get our results information from our parent component. Right now, we haven't set that up, so we'll need to do that.
Back to NytApp
In our NytApp
component, we have our results information saved in the state. If we want to render that information in our newly created NytResults
component we need to pass it as a prop to NytResults so that it can access it. But first in order to even use NytResults
in NytApp
we need to import it. Add the following import to your NytApp.js
file.
Cool, now we can use it in our render!! Directly underneath our closing </form>
tag, we can now use our NytResults
component.
Let's think through this code. First off notice that we're using another ternary, this time the condition we're checking for is if our results length is greater than zero, AKA do we have any results. If we do have results, then we want to display our NytResults component, if we don't then we can just display an empty div.
Notice the props that we are passing to the NytResults component. We're setting the prop results
equal to this.state.results
. So in order to access this prop in the NytResults component, we need to use props.results
since that's what we named our prop. If we named our prop nytResults instead of results then we would have to use props.nytResults
. But we didn't so we'll use just results.
Formatting & Displaying our Results
Let's set up our return to display something other than an empty <div>
. We're going to use our favorite, the super useful .map()
to nicely format our response. Instead of having to do for loop inside of for loop like in vanilla JS, we can just use map to accomplish the same thing. Make your NytResults
component look like this:
Let's walk through this code. We're taking props.results
and calling map on it. Reminder, map essentially takes every item in an array and performs the same action on it. So in this case, map is taking each result, and formatting it in JSX. Things specifically to notice:
unique
key
s are required when you create multiples of the same item (so when you use map). Luckily we have an id to use here.We're taking the main headline and putting it in an h2 tag
We use another ternary here to check if there is a more than 1 (AKA at least 2) things in the multimedia property. If there is at least 2, we want to display the image in the 2nd place
[1]
because that is a "large" size and not the "xl" size of[0]
.We put the snipper in a
<p>
tagWe have another ternary to check if there are keywords. If there are we display the string ' Keywords: '.
Then we use a list, and another map to put every keyword into a list item
Lastly, we make a link to the url of the article.
Hopefully you can see how much more streamlined this is than the vanilla JS version.
Pagination
Now, we've got our results displaying, but we currently have no way to look at anything but the 10 articles. If you remember back to the vanilla JS version we had pagination. So let's put that in place in our React app! First thing is, let's add a way to paginate to our parent component. If you look at your vanilla JS code, we had two separate functions for different directions of pagination, here we can just use one.
Add this function right above the render()
.
In changePageNumber
we are taking in the event, so we can preventDefault, and direction. The direction is going to tell us up or down, then we can incorporate the checks we need to. If the direction is down, we need to make sure that the pageNumber
is not 0 so we don't go into the negatives. If it's up we can just add 1! Then we're just fetching results again, after we changed our state to reflect the current correct page number.
Now that we have our method defined, we need a way to actually use it with our results. Since we only want the buttons for pagination to appear if we have results, let's put it in our NytResults
component. In order for us to be able to access it inside of that component we need to pass it as a prop! Let's update where we call NytResults
in our render to look like this:
Now, we are passing our function changePageNumber
to NytResults
as a prop called changePage
. So we'll need to use it as props.changePage
because that's what we named it.
Buttons to Change Page
Let's go to our NytResults
component and add the ability to call the method we just created in the parent component. Beneath our map, let's add the following code:
Here we're just creating two buttons, one that says Previous 10 and one that says Next 10. They're both calling the changePage
function we defined in the parent, and passing the corresponding direction. Hopefully you can see how we passed the method down to this child component through props.
Now, our app should work and be able to paginate!!!
One More Thing
So now when we change pages, it works, but what happens if we go to page 5 of one search, and want to search something else? We need make it so that when someone does a new search, the pageNumber
goes back to 0 every time, so they'll start on the first page of results.
Make your handleSubmit
method look like this:
That's it! You should now have a nicely working React application. Hopefully you can see some of the advantages of React over vanilla JS! Double check the completed code below. Also, feel free to style things however you want in this app.
Last updated