Mission Page: Dynamic Route Params

In the last lesson we added a click handler on the missions table row to navigate to a mission. But we did not define a Mission component or add a route to handle this new URL. In this lesson we'll do just that.

We've added a new Mission component which you can see here. Head on over to App.js to see how we set up this Route. We use the path /missions/:id as a "dynamic segment". From See React Router docs:

If a path segment starts with : then it becomes a "dynamic segment". When the route matches the URL, the dynamic segment will be parsed from the URL and provided as params to other router APIs.

So, when such a route is accessed, for example /missions/1, we will match this route and "1" will be provided into the Mission component as params. To access params, we'll use the useParams hook inside the Mission component. In the line const { id } = useParams(), we destructure the id off of the params. This is our mission ID.

We now need to find the mission- the only information we have inside the Mission component is the id at this point. So, we'll create a crude findMissionById function to find the mission based on the id using the javascript find function. Note: in the very near future, we will use Redux to properly select this mission using a selector.

We useMemo on this find to memoize this function so that it isn't computed again for the same ID. This isn't really necessary for our simple example but is good practice to understand that renders can happen multiple times and that React hooks can help us not recompute things again if it is not necessary.

If no mission is found, we escape the component early and return "No mission found". Else, now that we have our mission, we render the id and the title. Give it a shot, go click through each mission in the table and confirm that the data renders properly. Refresh on each mission in the browser to observe that each mission loads correctly.

Menu
Lesson 20/26
import { useMemo } from "react";
import { useParams } from "react-router-dom";
import { missions } from "./Missions";

function findMissionById(id) {
  return () => missions.find((mission) => mission.id == id);
}

function Mission() {
  const { id } = useParams();
  const mission = useMemo(findMissionById(id), [id]);
  if (!mission) {
    return <div> No mission found </div>;
  }
  const { title, description } = mission;
  return (
    <div>
      {" "}
      Mission {id}: {title}{" "}
    </div>
  );
}

export default Mission;