Dependent components with builtin data fetching

Suppose I have a page with those React components:

<CompetitionsPicker />
<SeasonsPicker />
<TeamsPicker />

Each of those component do some data fetching inside.

CompetitionsPicker provides a list of competitions. Competition. SeasonsPicker provides a list of seasons, this depends on Competition. Seasons(competition) TeamsPicker provides a list of teams, this depends on Competition and Season. Teams(competition, season).

Suppose that:

  • I want to make the above component reusable from multiple pages.

How can I structure the above in such a way I end up with something like:

<CompetitionsPicker /> // This modifies {competition} only
<SeasonsPicker competition={competition} /> This modifies {season} only
<TeamsPicker competition={competition} season={season} /> This modifies {team} only

I am having a hard time at coming up with something reusable. The above components are meant to be used by multiple pages (but some pages might use only two of the three above).

How can I structure the state for the above?

Answer

How can I structure the above in such a way I end up with something like:

<CompetitionsPicker /> // This modifies {competition} only
<SeasonsPicker competition={competition} /> This modifies {season} only
<TeamsPicker competition={competition} season={season} /> This modifies {team} only

Assuming you are using functional components style:

const [competition, setCompetition] = useState(null);
const [season, setSeason] = useState(null);
const [team, setTeam] = useState(null);

You need to add the setX... callbacks to each component’s props, so that they can “return” the value selected.

For example, your TeamsPicker needs to take an extra prop (onSelectTeam), which it should call when a team is selected:

<TeamsPicker competition={competition} season={season} onSelectTeam={setTeam} />

Now to make sure that each component has all the data it needs in order to function correctly, you can either decide to conditionally render the components when all their props are ready, example:

{<CompetitionsPicker onSelectCompetition={setCompetition} />}
{competition && <SeasonsPicker competition={competition} onSelectSeason={setSeason} />}
{(competition && season) && <TeamsPicker competition={competition} season={season} onSelectTeam={setTeam} />}

or have each component handle this condition by itself:

{<CompetitionsPicker onSelectCompetition={setCompetition} />}
{<SeasonsPicker competition={competition} onSelectSeason={setSeason} />}
{<TeamsPicker competition={competition} season={season} onSelectTeam={setTeam} />}

Now each component decides what to display until all the props it needs are supplied with valid values.