Cannot get props to pass through variable path /:id, react router dom

Viewed 361

The console.log confirms user input 'searchTerm' gets raise up from component by the onClick function.

Then saved to state in the handleClick function.

But it does not pass through to the second route.

    function App() {
      const [searchResults, setSearchResults] = useState([]);
      const [searchTerm, setsearchTerm] = useState('')
      const [single, setSingle] = useState();

      const fetchData = async (searchTerm) => {
        setsearchTerm(searchTerm)
        try {
          const { data } = await axios.get(`/data/${searchTerm}.json`)
          console.log(data)
          setSearchResults(data)
        } 
        catch(err) {
          const empty = [];
          setSearchResults(empty)
          console.log(err)
        }
      }

Next step, pass props through to 'SearchResultSingle' component, aka the second route

The console.log shows 'searchTerm' gets raise up from component onClick, and then saved to state in the function below, but it does not pass through to the second route.

      const handleClick = data => {
        console.log('click', data.clip)
        setSingle(data.clip)
      }

      return (
        <Router>
          <div>
            <SearchForm fetchData={fetchData}/>
            <Child searchTerm={searchTerm} />
            <Switch>
              <Route 
                path="/" 
                render={props=>
                  <SearchResults {...props} 
                  searchResults={searchResults}
                  searchTerm={searchTerm}
                  handleClick={handleClick}/>
                } 
              />

Second route, props are not passing through

              <Route 
                exact
                path={`/${searchTerm}/:id`} 
                render={props=>
                  <SearchResultSingle {...props} 
                  searchTerm={searchTerm}
                  searchResults={searchResults}
                  single={single}/>
                } 
              />

            </Switch>
          </div>
        </Router>
      );
    }

    export default App;
1 Answers

Issue

The Switch component returns and renders the first Route or Redirect to matches the path. The path="/" will match any path, and thus will always be matched, returned, and rendered by the Switch.

Solution

Reorder your routes to specify more specific paths before less specific paths.

<Switch>
  <Route 
    path={`/${searchTerm}/:id`} 
    render={props=>
      <SearchResultSingle
        {...props} 
        searchTerm={searchTerm}
        searchResults={searchResults}
        single={single}
      />
    } 
  />
  <Route 
    path="/" 
    render={props=>
      <SearchResults
        {...props} 
        searchResults={searchResults}
        searchTerm={searchTerm}
        handleClick={handleClick}
      />
    } 
  />
</Switch>
Related