mirror of
https://github.com/rjNemo/meal_planner
synced 2026-06-12 13:26:45 +00:00
refactor Router
This commit is contained in:
parent
d267c55323
commit
8fb5ca872c
13 changed files with 106 additions and 141 deletions
14
src/App.tsx
14
src/App.tsx
|
|
@ -1,17 +1,16 @@
|
||||||
import React, {FC, useState} from "react";
|
import React, { FC, useState } from "react";
|
||||||
import { Router } from "./utils/router";
|
import { Router } from "./router/Router";
|
||||||
|
|
||||||
import { PreLoader } from "./components/PreLoader";
|
import { PreLoader } from "./components/PreLoader";
|
||||||
|
|
||||||
import { useAuth0 } from "./utils/auth0-spa";
|
import { useAuth0 } from "./utils/auth0-spa";
|
||||||
import { getData } from "./utils/methods";
|
import { getData } from "./utils/methods";
|
||||||
import history from "./utils/history";
|
|
||||||
|
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import MainLayout from "./layouts/MainLayout";
|
import MainLayout from "./layouts/MainLayout";
|
||||||
import MainRouter from "./controllers/MainRouter";
|
import { AppRouter } from "./router";
|
||||||
|
|
||||||
export const App:FC = () => {
|
export const App: FC = () => {
|
||||||
const { loading } = useAuth0();
|
const { loading } = useAuth0();
|
||||||
const [searchString, setSearchString] = useState("");
|
const [searchString, setSearchString] = useState("");
|
||||||
const [searchResults, setSearchResults] = useState({ meals: [] });
|
const [searchResults, setSearchResults] = useState({ meals: [] });
|
||||||
|
|
@ -96,7 +95,6 @@ export const App:FC = () => {
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
const { value } = e.target;
|
const { value } = e.target;
|
||||||
setSearchString(value);
|
setSearchString(value);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return loading ? (
|
return loading ? (
|
||||||
|
|
@ -104,7 +102,7 @@ export const App:FC = () => {
|
||||||
<PreLoader />
|
<PreLoader />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Router >
|
<Router>
|
||||||
<MainLayout
|
<MainLayout
|
||||||
buttonUrl={buttonUrl}
|
buttonUrl={buttonUrl}
|
||||||
// meal={meal}
|
// meal={meal}
|
||||||
|
|
@ -117,7 +115,7 @@ export const App:FC = () => {
|
||||||
setSearchString={setSearchString}
|
setSearchString={setSearchString}
|
||||||
getSearchResults={getSearchResults}
|
getSearchResults={getSearchResults}
|
||||||
>
|
>
|
||||||
<MainRouter
|
<AppRouter
|
||||||
buttonUrl={buttonUrl}
|
buttonUrl={buttonUrl}
|
||||||
meal={meal}
|
meal={meal}
|
||||||
getMeal={getMeal}
|
getMeal={getMeal}
|
||||||
|
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { Switch, Route, Redirect } from "react-router-dom";
|
|
||||||
import { SearchController } from "./SearchController";
|
|
||||||
import { HomeController } from "./HomeController";
|
|
||||||
import { MealController } from "./MealController";
|
|
||||||
import { CategoryController } from "./CategoryController";
|
|
||||||
import { CategoryListController } from "./CategoryListController";
|
|
||||||
import { ProfileController } from "./ProfileController";
|
|
||||||
import { ContactPage } from "../pages/Contact";
|
|
||||||
import { NotFoundPage } from "../pages/NotFoundPage";
|
|
||||||
import { PrivateRoute } from "../components/PrivateRoute";
|
|
||||||
|
|
||||||
const MainRouter = ({
|
|
||||||
buttonUrl,
|
|
||||||
meal,
|
|
||||||
getMeal,
|
|
||||||
getRandomMeal,
|
|
||||||
searchString,
|
|
||||||
searchResults,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Switch>
|
|
||||||
<Route exact path="/">
|
|
||||||
<HomeController buttonUrl={buttonUrl} />
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<PrivateRoute exact path="/profile" component={ProfileController} />
|
|
||||||
|
|
||||||
<Route exact path={buttonUrl}>
|
|
||||||
<MealController
|
|
||||||
meal={meal}
|
|
||||||
getMeal={getMeal}
|
|
||||||
getRandomMeal={getRandomMeal}
|
|
||||||
/>
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route exact path="/categories">
|
|
||||||
<CategoryListController />
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route path="/categories/:strCategory/">
|
|
||||||
<CategoryController />
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route exact path="/search">
|
|
||||||
<SearchController
|
|
||||||
searchString={searchString}
|
|
||||||
searchResults={searchResults}
|
|
||||||
/>
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route path="/contact">
|
|
||||||
<ContactPage />
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route path="/404">
|
|
||||||
<NotFoundPage handleClick={getRandomMeal} />
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route path="/:id">
|
|
||||||
<MealController
|
|
||||||
meal={meal}
|
|
||||||
getMeal={getMeal}
|
|
||||||
getRandomMeal={getRandomMeal}
|
|
||||||
/>
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route path="*">
|
|
||||||
<Redirect to="/404" />
|
|
||||||
</Route>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MainRouter;
|
|
||||||
74
src/router/AppRouter.tsx
Normal file
74
src/router/AppRouter.tsx
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { Switch, Route, Redirect } from "react-router-dom";
|
||||||
|
import { SearchController } from "../containers/SearchController";
|
||||||
|
import { HomeController } from "../containers/HomeController";
|
||||||
|
import { MealController } from "../containers/MealController";
|
||||||
|
import { CategoryController } from "../containers/CategoryController";
|
||||||
|
import { CategoryListController } from "../containers/CategoryListController";
|
||||||
|
import { ProfileController } from "../containers/ProfileController";
|
||||||
|
import { ContactPage } from "../pages/Contact";
|
||||||
|
import { NotFoundPage } from "../pages/NotFoundPage";
|
||||||
|
import { PrivateRoute } from "./PrivateRoute";
|
||||||
|
|
||||||
|
//TODO: remove state from router move to containers
|
||||||
|
|
||||||
|
const AppRouter = ({
|
||||||
|
buttonUrl,
|
||||||
|
meal,
|
||||||
|
getMeal,
|
||||||
|
getRandomMeal,
|
||||||
|
searchString,
|
||||||
|
searchResults,
|
||||||
|
}) => (
|
||||||
|
<Switch>
|
||||||
|
<Route exact path="/">
|
||||||
|
<HomeController buttonUrl={buttonUrl} />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<PrivateRoute exact path="/profile" component={ProfileController} />
|
||||||
|
|
||||||
|
<Route exact path={buttonUrl}>
|
||||||
|
<MealController
|
||||||
|
meal={meal}
|
||||||
|
getMeal={getMeal}
|
||||||
|
getRandomMeal={getRandomMeal}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route exact path="/categories">
|
||||||
|
<CategoryListController />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route path="/categories/:strCategory/">
|
||||||
|
<CategoryController />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route exact path="/search">
|
||||||
|
<SearchController
|
||||||
|
searchString={searchString}
|
||||||
|
searchResults={searchResults}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route path="/contact">
|
||||||
|
<ContactPage />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route path="/404">
|
||||||
|
<NotFoundPage handleClick={getRandomMeal} />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route path="/:id">
|
||||||
|
<MealController
|
||||||
|
meal={meal}
|
||||||
|
getMeal={getMeal}
|
||||||
|
getRandomMeal={getRandomMeal}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route path="*">
|
||||||
|
<Redirect to="/404" />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default AppRouter;
|
||||||
|
|
@ -1,25 +1,24 @@
|
||||||
import React, { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Route } from "react-router-dom";
|
import { Route } from "react-router-dom";
|
||||||
import { useAuth0 } from "../utils/auth0-spa";
|
import { useAuth0 } from "../utils/auth0-spa";
|
||||||
|
|
||||||
|
// TODO use FC and props
|
||||||
export const PrivateRoute = ({ component: Component, path, ...rest }) => {
|
export const PrivateRoute = ({ component: Component, path, ...rest }) => {
|
||||||
const { loading, isAuthenticated, loginWithRedirect } = useAuth0();
|
const { loading, isAuthenticated, loginWithRedirect } = useAuth0();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// catches infinite loading when no user is logged in
|
||||||
if (loading || isAuthenticated) {
|
if (loading || isAuthenticated) {
|
||||||
// catches infinite loading when no user is logged in
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fn = async () => {
|
const fn = async () =>
|
||||||
await loginWithRedirect({
|
await loginWithRedirect({
|
||||||
appState: { targetUrl: path }
|
appState: { targetUrl: path },
|
||||||
});
|
});
|
||||||
};
|
|
||||||
fn();
|
fn();
|
||||||
}, [loading, isAuthenticated, loginWithRedirect, path]);
|
}, [loading, isAuthenticated, loginWithRedirect, path]);
|
||||||
|
|
||||||
const render = props =>
|
const render = (props) => (isAuthenticated ? <Component {...props} /> : null);
|
||||||
isAuthenticated === true ? <Component {...props} /> : null;
|
|
||||||
|
|
||||||
return <Route path={path} render={render} {...rest} />;
|
return <Route path={path} render={render} {...rest} />;
|
||||||
};
|
};
|
||||||
18
src/router/Router.tsx
Normal file
18
src/router/Router.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { Router as RouterOriginal, useLocation } from "react-router-dom";
|
||||||
|
import history from "../utils/history";
|
||||||
|
|
||||||
|
export const Router: FC = ({ children }) => (
|
||||||
|
<RouterOriginal history={history}>
|
||||||
|
<ScrollToTop />
|
||||||
|
{children}
|
||||||
|
</RouterOriginal>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ScrollToTop: FC = () => {
|
||||||
|
const location = useLocation();
|
||||||
|
useEffect(() => {
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
}, [location.pathname]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
2
src/router/index.ts
Normal file
2
src/router/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
import AppRouter from "./AppRouter";
|
||||||
|
export { AppRouter };
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
import React, { useMemo, useEffect } from "react";
|
|
||||||
import {
|
|
||||||
Router as RouterOriginal,
|
|
||||||
useParams,
|
|
||||||
useLocation,
|
|
||||||
useHistory,
|
|
||||||
useRouteMatch
|
|
||||||
} from "react-router-dom";
|
|
||||||
import queryString from "query-string";
|
|
||||||
|
|
||||||
import { createBrowserHistory } from "history";
|
|
||||||
export const history = createBrowserHistory();
|
|
||||||
|
|
||||||
export const Router = ({ children }) => {
|
|
||||||
return (
|
|
||||||
<RouterOriginal history={history}>
|
|
||||||
<ScrollToTop />
|
|
||||||
{children}
|
|
||||||
</RouterOriginal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ScrollToTop = () => {
|
|
||||||
const location = useLocation();
|
|
||||||
useEffect(() => {
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
}, [location.pathname]);
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useRouter = () => {
|
|
||||||
const params = useParams();
|
|
||||||
const location = useLocation();
|
|
||||||
const history = useHistory();
|
|
||||||
const match = useRouteMatch();
|
|
||||||
|
|
||||||
return useMemo(() => {
|
|
||||||
return {
|
|
||||||
push: history.push,
|
|
||||||
replace: history.replace,
|
|
||||||
pathname: location.pathname,
|
|
||||||
query: {
|
|
||||||
...queryString.parse(location.search),
|
|
||||||
...params
|
|
||||||
},
|
|
||||||
match,
|
|
||||||
location,
|
|
||||||
history
|
|
||||||
};
|
|
||||||
}, [params, match, location, history]);
|
|
||||||
};
|
|
||||||
Loading…
Reference in a new issue