For visualisation and clear picture, I will show the app's screen shot first.
I'm using github api to fetch Repos and Users. Simple. Now this how App.tsx looks;
// App.tsx
import React from "react";
import MainSearchPage from "./Components/MainSearchPage";
import Header from "./Components/Header";
import "./Sass/main.scss";
const App: React.FC = () => {
return (
<div className="App">
<Header />
<MainSearchPage />
</div>
);
};
export default App;
This is the MainSearchPage component;
// MainSearchPage.tsx
import React, { useContext } from "react";
import { GithubContext } from "../Context/GithubContext";
import searchPc from "../Icons/search-pc.svg";
import SearchResults from "./SearchResults";
const MainSearchPage: React.FC = () => {
const { isSearched } = useContext(GithubContext);
return (
<div>
{isSearched ? (
<SearchResults />
) : (
<div className="blank-search-page">
<div className="blank-search-page__items">
<img src={searchPc} alt="search-pc" />
<p>Search results will appear here</p>
</div>
</div>
)}
</div>
);
};
export default MainSearchPage;
When input changes, isSearch becomes true and SearchResults is rendering. This is the SearchResults, where the problem begins.
//SearchResults.tsx
import React from "react";
import { Route, BrowserRouter as Router, Switch } from "react-router-dom";
import MainSearchResults from "./MainSearchResults";
import SideBarSearchResults from "./SideBarSearchResults";
import UsersPage from "./UsersPage";
const SearchResults = () => {
return (
<div className="search-results">
<Router>
<SideBarSearchResults />
<Switch>
<Route path="/" component={MainSearchResults} />
<Route path="/search-users" component={UsersPage} />
</Switch>
</Router>
</div>
);
};
export default SearchResults;
So MainSearchResults is basically repo results on the right. Sidebar is obvious I suppose. And UsersPage is the component that should be rendered when I click the Users on the left. But nothing happens when I click. Url changes and that's it. No errors in the console or anything. It was working before I put "isSearched" state. But I don't think it should matter.
SideBar component;
//SideBarSearchResults.tsx
import React, { useContext } from "react";
import repositoriesSVG from "../Icons/repositories.svg";
import usersSVG from "../Icons/users.svg";
import bookmarkblackSVG from "../Icons/bookmarkblack.svg";
import { Link } from "react-router-dom";
import { GithubContext } from "../Context/GithubContext";
const SideBarSearchResults: React.FC = () => {
const { repoCount, userCount } = useContext(GithubContext);
return (
<div className="side-bar-search-results">
<Link to="/">
<div className="side-bar-search-results__repositories">
<img src={repositoriesSVG} alt="repo" />
<p className="result-title">Repositories</p>
<p className="quantity">{repoCount ?? 0}</p>
</div>
</Link>
<Link to="/search-users">
<div className="side-bar-search-results__users">
<img src={usersSVG} alt="users" />
<p className="result-title">Users</p>
<p className="quantity">{userCount ?? 0}</p>
</div>
</Link>
<div className="side-bar-search-results__bookmarked ">
<img src={bookmarkblackSVG} alt="bookmarked" />
<Link to="/repo-details">
<p className="result-title">Bookmarked</p>
</Link>
<p className="quantity">15</p>
</div>
</div>
);
};
export default SideBarSearchResults;
The Switch
component matches and renders the first matched path, and "/" is a prefix for every path. In other words, it will always be the path matched and returned first.
Reorder your Route
s to specify the more specific paths first, and go in descending order of path specificity.
<Router>
<SideBarSearchResults />
<Switch>
<Route path="/search-users" component={UsersPage} />
<Route path="/" component={MainSearchResults} />
</Switch>
</Router>
As a complement to Drew Reese's anwer answer:
When you use any route matching component you need to know how it works so that you may go for another library. In case react-router
<Router/>
, it doesn't render a component exclusively by default. Meaning, your application could possibly end up matching two paths for one route and renders the first one so order does matter . For example, if you want to route '/products'
, it matches both /
and /products
. That was your case . How to solve this:
exact
or,Alternative:
What if you don't like this path matching of react-router?
Here you have Reach Router whose path matching is a bit different. Reach Router ranks the paths and renders the one that makes the most sense. You can read about their path ranking . So, you don't need to think about the orders or using an extra keyword exact
because reach router itself prioritizes the router using the path ranking**system .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.