3

Please see the full code on codesandbox.

I have two Route components for my countries api app-

<>
    <Header/>

    <Router>
        <Switch>
            <CountriesDataProvider>

                <Route path='/' exact component={HomeRoute} />
                <Route path='/detail/:countryName' component={DetailsRoute} />
                        
            </CountriesDataProvider>
        </Switch>
    </Router>
</>

The DetailsRoute for each country shows up with all information perfectly when I click on a country on the HomeRoute. But when a direct http request is made or the DetailsRoute is refreshed, I see this error-

/src/comps/Details/DetailsRoute.jsx

Cannot read property 'borders' of undefined

It occurs on the line-

const promises = country[0].borders.map(fetchNeighborName);

country[0] is extracted from countriesData which seems to be undefined-

const {countriesData} = React.useContext(CountriesDataContext);

This is not an issue with BrowserRouter, because the DetailsRoute component does render but with missing info.

I don't kow what logical error is causing it to not work when a direct url request is sent to the DetailsRoute component? Please let me know the fix!

Sapinder
  • 183
  • 10
  • I think this is can be related to https://stackoverflow.com/questions/53453861/react-context-api-persist-data-on-page-refresh – Mehmet Ali Peker Sep 18 '20 at 00:37
  • @MehmetAliPeker I couldn't relate that to my problem. The issue I see when I set *breakpoints* in `CountriesDataContext` is that on reload, `componentDidMount` doesn't execute, and that's where I *fetch* the data for countries. – Sapinder Sep 18 '20 at 01:17

1 Answers1

0

The problem is that when you reload the details page the response in CountriesDataContext hasn't come back yet, so country is empty. An easy way to solve the problem (and is generally good practice) is to add a check to make sure the data is there:

async function resolveBorders() {
  // Add a condition to make sure you have the data you expect.
  if (country.length) {
    const promises = country[0].borders.map(fetchNeighborName);
    setBorderCountries(await Promise.all(promises));
  }
}

Be sure to also add country to the effect's dependency array so that the effect runs again when the response comes back:

React.useEffect(() => {
  async function resolveBorders() {
    ...
  }

  resolveBorders();
}, [borderCountries, country]); // <-- Add `country` here
ericgio
  • 2,121
  • 2
  • 18
  • 37