У меня есть следующая структура в моем приложении React, используя react-router-dom
.
<Router>
<Header/>
<Main>
<AllRoutes> // THIS HANDLES THE SWITCH WITH ALL THE ROUTES
<Switch>
<Route exact path={ROUTES.HOME} component={Home}/>
<Route exact path={ROUTES.ABOUT} component={About}/>
<Route exact path={ROUTES.PRIVACY} component={Privacy}/>
// ETC
</Switch>
</AllRoutes>
</Main>
<Footer/> // <==== FOOTER NEEDS TO KNOW WHICH ROUTE HAS BEEN MATCH
<Router>
ВОПРОС
Нижний колонтитул должен знать, что <Route/>
был совпадением. Каков наилучший шаблон для этого?
ВАРИАНТ # 1
Я обнаружил, что useRouteMatch
перехватывает реагирует на документы маршрутизатора :
Это вроде бы сработает, но я не думаю это достаточно хорошо для моей ситуации. Потому что строка URL-адреса может соответствовать маршруту и в то же время не быть действительным маршрутом.
Например:
- Маршрут:
/:language/privacy
- Действительный маршрут:
/en/privacy
- Недействительный маршрут, который также может совпадать:
/notALanguage/privacy
После того, как маршрут имеет совпадение, мне обычно нужно проверить, действителен ли он перед рендерингом страница компонента или страница 404.
Например:
<Route exact path={"/:language/privacy"} render={(routeProps) => {
const possibleLanguage = routeProps.match.params.language;
if (possibleLanguage in LANGUAGES) {
return(
<PrivacyPage lang={possibleLanguage}/>
);
}
else {
return(
<Page404/>
);
}
}}/>
ВАРИАНТ № 2
Я думаю о следующем:
App.js
звонки useLocation
. Таким образом, он всегда выполняет повторную визуализацию при изменении маршрута. - Я мог бы добавить функцию
detectRoute
в App.js
, чтобы заранее выполнить всю проверку маршрута. - И мой
AllRoutes
компоненту не нужен компонент. Я бы реализовал собственный переключатель JS и отобразил соответствующий маршрут. - Таким образом, я заранее знаю, какой
<Route/>
будет соответствовать, и могу передать его <Footer/>
или любому компоненту, который находится вне из совпавших <Route/>
.
Примерно так:
SandBox Link
export default function App() {
console.log("Rendering App...");
const location = useLocation();
// THIS WOULD BE THE detectRoute FUNCTION
// I COULD EVEN USE THE useRouteMatch HOOK IN HERE
const matchedRoute =
location.pathname === ROUTE1
? "ROUTE1"
: location.pathname === ROUTE2
? "ROUTE2"
: "404";
return (
<div>
<div className="App">
<Link to={ROUTE1}>Route 1</Link>
<Link to={ROUTE2}>Route 2</Link>
<Link to={"/whatever"}>Route 404</Link>
</div>
<div>
<AllRoutes matchedRoute={matchedRoute} />
</div>
</div>
);
}
function AllRoutes(props) {
switch (props.matchedRoute) {
case "ROUTE1":
return <Route exact path={ROUTE1} component={Page1} />;
case "ROUTE2":
return <Route exact path={ROUTE2} component={Page2} />;
default:
return <Route exact path={"*"} component={Page404} />;
}
}
Работает. Но я хотел бы знать, есть ли правильный способ сделать это, потому что это кажется немного странным и может быть что-то специально разработанное для этого.