Home > Software design >  Reac router component in a list as a state
Reac router component in a list as a state

Time:09-12

does anyone have experience with React routers?Is there a way to create a list of routes and hold it in a usestate? When i try to do the [... prevCountryRoutes] i get the error that prevCountryRoutes is not iterable

 const [countriesWithRouteList,setCountriesWithRouteList]=React.useState(JSON.parse(localStorage.getItem("countriesWithRouteList")) || [])
 const [countryRoutes,setCountryRoutes]=React.useState()

function addCountryRoute(co){
   if(countriesWithRouteList.filter(el => el == co) == null){
     console.log('already route exists')
   }else{
     console.log('country page being added')
     setCountryRoutes((prevCountryRoutes)=>{
       const newRoute = <Route 
         key={nanoid()}
         path={`/countrypage/${co.replace(/ /g, ' ')}`} 
         element={
           <CountryPage 
             country={co}
             holidays={holidays}
             handleDeleteClick={handleDeleteClick}
             handleFormSubmit={handleFormSubmit}
           />
         }
       />
       return(
         [...prevCountryRoutes, newRoute]
       )
     })
   }
   setCountriesWithRouteList(prevList => [...prevList, co])
 }

CodePudding user response:

Initialize countryRoutes with an array, so the first time can be iterable.

const [countryRoutes,setCountryRoutes] = React.useState([])

CodePudding user response:

The error you are asking about is cause by not declaring an initial countryRoutes state that is iterable. It's undefined.

Anyway, it's a React anti-pattern to store React components and JSX in state. Just store the data and render the derived JSX from state.

I suggest the following refactor:

const [countries, setCountries] = React.useState(JSON.parse(localStorage.getItem("countries")) || []);

function addCountryRoute(co){
  if (countries.some(el => el.co === co)){
    console.log('already route exists')
  } else {
    console.log('country page being added')
    setCountries((countries) => countries.concat({
      id: nanoid(),
      co,
    }));
  }
}

...

{countries.map(country => (
  <Route 
    key={country.id}
    path={`/countrypage/${co.replace(/ /g, ' ')}`} 
    element={
      <CountryPage 
        country={co}
        holidays={holidays}
        handleDeleteClick={handleDeleteClick}
        handleFormSubmit={handleFormSubmit}
      />
    }
  />
))}

And instead of mapping a bunch of routes that differ only in the country path segment, render just a single route where the country code is a route path parameter and the CountryPage component uses the useParams hook to get the code.

Example:

<Route 
  path="/countrypage/:country" 
  element={
    <CountryPage
      holidays={holidays}
      handleDeleteClick={handleDeleteClick}
      handleFormSubmit={handleFormSubmit}
    />
  }
/>

CountryPage

const { country } = useParams();
  • Related