From 73ec7304c289a585c1018457ba638a30bc9a8090 Mon Sep 17 00:00:00 2001 From: Josh Pensky Date: Mon, 13 Sep 2021 16:23:52 -0400 Subject: [PATCH 1/3] throw up error for same-path-same-params redirects --- demos/intermediate/src/router/index.tsx | 13 +++++++++++-- package/src/Guard.tsx | 10 +++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/demos/intermediate/src/router/index.tsx b/demos/intermediate/src/router/index.tsx index 7c2cc20..38ddb0e 100644 --- a/demos/intermediate/src/router/index.tsx +++ b/demos/intermediate/src/router/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Router as BrowserRouter, Switch } from 'react-router-dom'; -import { GuardProvider, GuardedRoute } from 'react-router-guards'; +import { GuardProvider, GuardedRoute, GuardFunction } from 'react-router-guards'; import { Detail, List, Loading, NotFound } from 'containers'; import { beforeRouteEnter as detailBeforeEnter } from 'containers/Detail'; import history from './history'; @@ -10,6 +10,15 @@ interface Props { children(content: React.ReactElement): React.ReactElement; } +const invalidName: GuardFunction = (to, from, next) => { + const { name } = to.match.params; + if (name === 'test') { + next.redirect('/test'); + } else { + next(); + } +}; + const Router: React.FunctionComponent = ({ children }) => ( @@ -20,7 +29,7 @@ const Router: React.FunctionComponent = ({ children }) => ( path="/:name" exact component={Detail} - guards={[waitOneSecond, detailBeforeEnter]} + guards={[invalidName, waitOneSecond, detailBeforeEnter]} /> , diff --git a/package/src/Guard.tsx b/package/src/Guard.tsx index e27d94c..7d4b824 100644 --- a/package/src/Guard.tsx +++ b/package/src/Guard.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useContext, useEffect, useMemo } from 'react'; import { __RouterContext as RouterContext } from 'react-router'; -import { matchPath, Redirect, Route } from 'react-router-dom'; +import { Redirect, Route } from 'react-router-dom'; import { ErrorPageContext, FromRouteContext, GuardContext, LoadingPageContext } from './contexts'; import { usePrevious, useStateRef, useStateWhenMounted } from './hooks'; import renderPage from './renderPage'; @@ -171,11 +171,11 @@ const Guard: React.FunctionComponent = ({ children, component, meta, } else if (routeError) { return renderPage(ErrorPage, { ...routeProps, error: routeError }); } else if (routeRedirect) { - const pathToMatch = typeof routeRedirect === 'string' ? routeRedirect : routeRedirect.pathname; - const { path, isExact: exact } = routeProps.match; - if (pathToMatch && !matchPath(pathToMatch, { path, exact })) { - return ; + const redirectPath = typeof routeRedirect === 'string' ? routeRedirect : routeRedirect.pathname; + if (redirectPath === routeProps.location.pathname) { + return renderPage(ErrorPage, { ...routeProps, error: 'Infinite redirect.' }); } + return ; } return ( From 96b6f279c570821ef908a84c4086630b84d31ef0 Mon Sep 17 00:00:00 2001 From: Josh Pensky Date: Mon, 13 Sep 2021 16:34:39 -0400 Subject: [PATCH 2/3] relocate infinite logic to validateRoute --- package/src/Guard.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/package/src/Guard.tsx b/package/src/Guard.tsx index 7d4b824..17b9db9 100644 --- a/package/src/Guard.tsx +++ b/package/src/Guard.tsx @@ -133,6 +133,15 @@ const Guard: React.FunctionComponent = ({ children, component, meta, const { props, redirect } = await resolveAllGuards(); pageProps = props; routeRedirect = redirect; + + // If there's a redirect, determine if it'll be infinite and throw error if so + if (routeRedirect) { + const redirectPath = + typeof routeRedirect === 'string' ? routeRedirect : routeRedirect.pathname; + if (redirectPath === routeProps.location.pathname) { + throw new Error('Infinite redirect.'); + } + } } catch (error) { routeError = error.message || 'Not found.'; } @@ -171,10 +180,6 @@ const Guard: React.FunctionComponent = ({ children, component, meta, } else if (routeError) { return renderPage(ErrorPage, { ...routeProps, error: routeError }); } else if (routeRedirect) { - const redirectPath = typeof routeRedirect === 'string' ? routeRedirect : routeRedirect.pathname; - if (redirectPath === routeProps.location.pathname) { - return renderPage(ErrorPage, { ...routeProps, error: 'Infinite redirect.' }); - } return ; } return ( From 95a644baaec6c8c3b878666f2cb096428c1f64d7 Mon Sep 17 00:00:00 2001 From: Josh Pensky Date: Mon, 13 Sep 2021 16:47:51 -0400 Subject: [PATCH 3/3] remove example, update errors --- demos/intermediate/src/router/index.tsx | 13 ++----------- package/src/Guard.tsx | 4 ++-- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/demos/intermediate/src/router/index.tsx b/demos/intermediate/src/router/index.tsx index 38ddb0e..7c2cc20 100644 --- a/demos/intermediate/src/router/index.tsx +++ b/demos/intermediate/src/router/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Router as BrowserRouter, Switch } from 'react-router-dom'; -import { GuardProvider, GuardedRoute, GuardFunction } from 'react-router-guards'; +import { GuardProvider, GuardedRoute } from 'react-router-guards'; import { Detail, List, Loading, NotFound } from 'containers'; import { beforeRouteEnter as detailBeforeEnter } from 'containers/Detail'; import history from './history'; @@ -10,15 +10,6 @@ interface Props { children(content: React.ReactElement): React.ReactElement; } -const invalidName: GuardFunction = (to, from, next) => { - const { name } = to.match.params; - if (name === 'test') { - next.redirect('/test'); - } else { - next(); - } -}; - const Router: React.FunctionComponent = ({ children }) => ( @@ -29,7 +20,7 @@ const Router: React.FunctionComponent = ({ children }) => ( path="/:name" exact component={Detail} - guards={[invalidName, waitOneSecond, detailBeforeEnter]} + guards={[waitOneSecond, detailBeforeEnter]} /> , diff --git a/package/src/Guard.tsx b/package/src/Guard.tsx index 17b9db9..97db539 100644 --- a/package/src/Guard.tsx +++ b/package/src/Guard.tsx @@ -139,11 +139,11 @@ const Guard: React.FunctionComponent = ({ children, component, meta, const redirectPath = typeof routeRedirect === 'string' ? routeRedirect : routeRedirect.pathname; if (redirectPath === routeProps.location.pathname) { - throw new Error('Infinite redirect.'); + throw new Error('rrg/infinite-redirect'); } } } catch (error) { - routeError = error.message || 'Not found.'; + routeError = error.message || 'rrg/error'; } if (currentRequests === getValidationsRequested()) {