Spotlight On
Rendering show/detail components in a SPA (single-page application) using React.js
In this small series of blog posts about the React/Redux project, I would like to focus on another challenge I tackled, which was showing and hiding show components of a particular resource. Specifically in my case, hiding and showing the details of a trail day event.
Some quick background for those just tuning in; this is a feature of an app that I wrote for my React/Redux (final) project for the Flatiron School boot camp. It is a single-page application that models an incentive program that encourages users to volunteer for trail days by earning points and redeeming those points for rewards.
Ok, on to the content.
Upon first navigating to the /events
path, you’ll be greeted by the future events rendered in a card deck with some basic info for each.
If a user wants more information on an event, they can click the “Show Detail” button originally would have rendered a separate detail component and routed the user away from the event index. However, I wanted the page to be a bit more interactive and flexible, so I opted to render the detail component in addition to the card deck. This still changes the url, but also allows the user to swap out which event is detailed, without having to go back to the index.
The way to set this up is to render the components based on the current url. In fact, this is similar to the design necessary to render the different index components and login/signup forms. The difference here is that we want the url to be dynamic and show the event resource that corresponds to the :id
param in the url. To do this, we will make use of the routerParams
that get passed by default into the render
prop of the Route
component. This si will require that you send a function to that prop as well, to which the routerProps
will be sent as an argument.
<Route path="/events" render={routerProps => <EventsPage {...routerProps} />} />
We will need the match
property from routerProps
to match a resource to the url. Since EventsPage
is the container that will render the index and detailed component, we’ll set that up next.
Events Container
In this component, we’ll set up a Route
that renders the detailed view of the event we’re interested in.
<CardDeck>
{events.map(e => <Event user={user} handleClick={this.handleClick} key={e.id} event={e}/>)}
</CardDeck>
<Route path={`${match.url}/:eventId`} render={routerProps => <EventDetail {...routerProps} user={user} events={events}/>} />
We pass routerProps
down to the EventDetail
component so that it can access the param (:eventId
) and grab the correct Event. Once the url contains a parameter for eventId
, the route will render the EventDetail
component.
Event Detail Component
Upon being rendered, this component will check the match.params
from props and make sure that an event can be found that corresponds to the :eventId
param. If not, instead of throwing an error, the component simply won’t render.
let {match, events} = props
let event = events.find(e => parseInt(match.params.eventId) === e.id)
Then we’ll use an if statement to check if the event is found, rendering it if it does, or rendering null otherwise.
Thanks for reading!