8. Exercise: Display data for track details page
3m

Goal

Display data for the track details page. When you click on a track from the homepage, you should see ALL the details for a track.

For example, you should be able to click on the first track of the homepage (or go to http://localhost:3000/track/c_0) and see the same details as we can see in this page in the demo app.

Step-by-step solution

Open up the src/pages/track-details-page.js file.

  1. Import the gql and useQuery modules from the @apollo/client package.

    import {useQuery, gql} from '@apollo/client';
  2. Create a new variable for the query called GET_TRACK_DETAILS. This will be set to the query we built in Sandbox earlier, wrapped with the gql tag.

    const GET_TRACK_DETAILS = gql`
    query GetTrackDetails($trackId: ID!) {
    track(id: $trackId) {
    id
    title
    author {
    id
    name
    photo
    }
    thumbnail
    length
    modulesCount
    numberOfViews
    modules {
    id
    title
    length
    }
    description
    }
    }
    `;
  3. Inside the Track component, we'll use the useQuery hook, passing it the GET_TRACK_DETAILS query. We'll also retrieve the loading, error, data properties from the result.

    const Track = () => {
    let {trackId} = useParams(); // get trackId from the URL params
    const {loading, error, data} = useQuery(GET_TRACK_DETAILS);
    return (
    <Layout>
    TODO: Replace me with track details for this track id: {trackId}!
    </Layout>
    );
    };
  4. We need to pass our query a variable called trackId. As the second argument to the useQuery hook, add the variables option, passing it the trackId. We get access to this trackId value from the useParams hook in the line above (using React Router).

    const Track = () => {
    let {trackId} = useParams(); // get trackId from the URL params
    const {loading, error, data} = useQuery(GET_TRACK_DETAILS, {
    variables: {trackId}
    });
    return (
    <Layout>
    TODO: Replace me with track details for this track id: {trackId}!
    </Layout>
    );
    };
  5. As before, we'll handle the rendering for the loading and error states.

    if (loading) {
    return <Loading />;
    }
    if (error) {
    return <p>ERROR: {error.message}</p>;
    }
  6. Finally, we'll handle rendering the TrackDetail component when the data is available.

    if (data) {
    return (
    <Layout>
    <TrackDetail track={data.track} />
    </Layout>
    );
    }

Full solution

Check your work

After completing this exercise, your app should look like this:

Bonus: Module details page

When you click "Start track" in the track details page, you should see a similar page as we can see in the demo app.

src/pages/module-details-page.js
import React from 'react';
import {useParams} from 'react-router-dom';
import {useQuery, gql} from '@apollo/client';
import {Layout, ModuleDetail, Loading} from '../components';
/**
* GET_MODULE_AND_PARENT_TRACK gql query to retrieve a specific module and its parent track,
* both needed for the ModuleDetail component
*/
const GET_MODULE_AND_PARENT_TRACK = gql`
query GetModuleAndParentTrack($moduleId: ID!, $trackId: ID!) {
module(id: $moduleId) {
id
title
content
videoUrl
}
track(id: $trackId) {
id
title
modules {
id
title
length
}
}
}
`;
/**
* Module page fetches both parent track and module's data from the gql query GET_MODULE_AND_PARENT_TRACK
* and feeds them to the ModuleDetail component
*/
const Module = () => {
let {trackId, moduleId} = useParams(); // get trackId and moduleId from the URL params
const {loading, error, data} = useQuery(GET_MODULE_AND_PARENT_TRACK, {
variables: {moduleId, trackId}
});
if (loading) {
return <Loading />;
}
if (error) {
return <p>ERROR: {error.message}</p>;
}
if (data) {
return (
<Layout fullWidth>
<ModuleDetail track={data.track} module={data.module} />
</Layout>
);
}
};
export default Module;
Previous
Next