Data in React
So now we want to add a third page: a page where we can watch the trailer. This is going to be an application of what we know already.
Create a new file in js/ called Details.js. In Details put:
In ClientApp.js, put your new route:
Here we’ve added a URL parameter using the colon. Now as a prop to Details you’ll get whatever :id was. So now try to manually change the anchor on your url to be http://localhost:8080/#/details/1
. You should see your new component here.
Let’s show you a neat debugging tip I totally stole from Ryan Florence. replace that h1 with this:
// ENDTODO
This is a useful way to dump your params to the page to see what react-router is giving you. This is awesome for state too; it shows you in real time what your state looks like. We’ll dig into React Tools here in a sec for even better debugging but for now let’s keep trucking with our Details.js.
We’re going to show all the details of a show on this page and be able to play the trailer. There’s a big problem here that we don’t have that data on this page though; it’s available in the Search route. We could require in data.json here given that our data is available that way but that typically isn’t the case: we typically get this data from the server. If that’s the case, you don’t want to make two AJAX requests to get the same data. In other words, we need to share this state between components. The way you do this is by pushing up the state to the highest common ancestor component. In this case, that’d be the router in ClientApp. So let’s first refactor Search to still work while it pulls in that data from Search.
Now make Search use it
Cool. Now it should still work but Search no longer controls the data but merely receives it as props. Now we can share this data with Details. Another thing to notice is that with components, you can pass them functions that return markup, essentially a render function inside of component. Indeed you can do this anywhere you can put a components. These are called stateless functional components. We’ll see more of these later.
Now we’re going to pass the correct show to the Details page. There’s a bunch of ways to do this:
- We could pass all the shows and let Details select the correct show. This isn’t great because Details is given an additional concern it doesn’t need to have.
- We could create a callback in ClientApp that it passes to Details that Details calls with the correct ID and ClientApp hands back the correct show. This is slightly better but it’s an odd API for getting data. Ideally we just hand down props and not a callback, especially since this isn’t async.
- Or we could hook into react-router’s ability to pass props down through stateless functions like we did with Search and just pass down the correct show. This is the best approach.
Add the following to ClientApp:
This should put the correct show as one of the props that ClientApp passes down to Details. If you refresh the page, you should see it now.
As an aside, I’ve found the best way to organize React method component is the following
- propTypes
- getInitialState / constructor
- Other lifecycle methods like componentDidUpdate (we’ll talk about those in a sec)
- Your methods you create (like assignShow)
- render
Makes it easier to find things when you look for them.
So let’s actually display some cool stuff:
Now you should have some nice looking UI.
Well, now we have a header in two places. That’s a strong indicator that you should make it’s its own component. Let’s abstract that in a component and use that in both places. Create a new file called Header.js and put this in there:
We’re even going to throw in a link back to the home page for fun. Now open Details.js and put:
Let’s put a back button on the Header so you can get back to Search after you reach it.
So let’s integrate this to Search. But it’s not so simple since on Search we want the header to have a search input and on Details we want a back button. So let’s see how to do that. In Header.js put:
In Search.js:
This is how you have a child component modify a parent’s state: you pass down the callback and let it call the parent to let the parent modify the state. This also demonstrates how to conditionally show one component and not another.
Lastly let’s make our show cards clickable.