mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	fix: redirect only happening on root path with replace (#2981)
Adds a fix for overeager redirects, now we will redirect on the root path and replace on our redirects from login. Co-authored-by: Gastón Fournier <gaston@getunleash.ai>
This commit is contained in:
		
							parent
							
								
									99f45b4248
								
							
						
					
					
						commit
						38be01f506
					
				| @ -1,5 +1,5 @@ | ||||
| import { Suspense, useCallback, useEffect, useState, useRef } from 'react'; | ||||
| import { Route, Routes, useNavigate } from 'react-router-dom'; | ||||
| import { Suspense } from 'react'; | ||||
| import { Route, Routes } from 'react-router-dom'; | ||||
| import { ErrorBoundary } from 'react-error-boundary'; | ||||
| import { Error } from 'component/layout/Error/Error'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| @ -16,47 +16,10 @@ import { useAuthDetails } from 'hooks/api/getters/useAuth/useAuthDetails'; | ||||
| import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser'; | ||||
| import { SplashPageRedirect } from 'component/splash/SplashPageRedirect/SplashPageRedirect'; | ||||
| import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| import useProjects from '../hooks/api/getters/useProjects/useProjects'; | ||||
| import { useLastViewedProject } from '../hooks/useLastViewedProject'; | ||||
| 
 | ||||
| import MaintenanceBanner from './maintenance/MaintenanceBanner'; | ||||
| import { styled } from '@mui/material'; | ||||
| 
 | ||||
| const InitialRedirect = () => { | ||||
|     const { lastViewed } = useLastViewedProject(); | ||||
|     const { projects, loading } = useProjects(); | ||||
|     const navigate = useNavigate(); | ||||
|     const ref = useRef<{ redirected: boolean }>({ redirected: false }); | ||||
| 
 | ||||
|     // Redirect based on project and last viewed
 | ||||
|     const getRedirect = useCallback(() => { | ||||
|         if (projects && lastViewed) { | ||||
|             return `/projects/${lastViewed}`; | ||||
|         } | ||||
| 
 | ||||
|         if (projects && !lastViewed && projects.length === 1) { | ||||
|             return `/projects/${projects[0].id}`; | ||||
|         } | ||||
| 
 | ||||
|         return '/projects'; | ||||
|     }, [lastViewed, projects]); | ||||
| 
 | ||||
|     const redirect = () => { | ||||
|         ref.current = { redirected: true }; | ||||
|         navigate(getRedirect(), { replace: true }); | ||||
|     }; | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         if (ref.current?.redirected === true) return; | ||||
| 
 | ||||
|         redirect(); | ||||
|     }, [getRedirect]); | ||||
| 
 | ||||
|     if (loading) { | ||||
|         return <Loader />; | ||||
|     } | ||||
| 
 | ||||
|     return <></>; | ||||
| }; | ||||
| import { InitialRedirect } from './InitialRedirect'; | ||||
| 
 | ||||
| const StyledContainer = styled('div')(() => ({ | ||||
|     '& ul': { | ||||
| @ -115,22 +78,15 @@ export const App = () => { | ||||
|                                                     } | ||||
|                                                 /> | ||||
|                                             ))} | ||||
|                                             <Route | ||||
|                                                 path="/" | ||||
|                                                 element={<InitialRedirect />} | ||||
|                                             /> | ||||
|                                             <Route | ||||
|                                                 path="*" | ||||
|                                                 element={<NotFound />} | ||||
|                                             /> | ||||
|                                         </Routes> | ||||
|                                         {/* Only redirect if we are not in test mode */} | ||||
|                                         <ConditionallyRender | ||||
|                                             condition={ | ||||
|                                                 !( | ||||
|                                                     import.meta.env | ||||
|                                                         .VITE_TEST_REDIRECT === | ||||
|                                                     'true' | ||||
|                                                 ) | ||||
|                                             } | ||||
|                                             show={<InitialRedirect />} | ||||
|                                         /> | ||||
| 
 | ||||
|                                         <FeedbackNPS openUrl="http://feedback.unleash.run" /> | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										39
									
								
								frontend/src/component/InitialRedirect.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								frontend/src/component/InitialRedirect.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| import { useCallback, useEffect, useContext } from 'react'; | ||||
| import { useNavigate } from 'react-router-dom'; | ||||
| import useProjects from '../hooks/api/getters/useProjects/useProjects'; | ||||
| import { useLastViewedProject } from '../hooks/useLastViewedProject'; | ||||
| import UIContext from 'contexts/UIContext'; | ||||
| import Loader from './common/Loader/Loader'; | ||||
| 
 | ||||
| export const InitialRedirect = () => { | ||||
|     const { lastViewed } = useLastViewedProject(); | ||||
|     const { projects, loading } = useProjects(); | ||||
|     const navigate = useNavigate(); | ||||
| 
 | ||||
|     // Redirect based on project and last viewed
 | ||||
|     const getRedirect = useCallback(() => { | ||||
|         if (projects && lastViewed) { | ||||
|             return `/projects/${lastViewed}`; | ||||
|         } | ||||
| 
 | ||||
|         if (projects && !lastViewed && projects.length === 1) { | ||||
|             return `/projects/${projects[0].id}`; | ||||
|         } | ||||
| 
 | ||||
|         return '/projects'; | ||||
|     }, [lastViewed, projects]); | ||||
| 
 | ||||
|     const redirect = () => { | ||||
|         navigate(getRedirect(), { replace: true }); | ||||
|     }; | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         redirect(); | ||||
|     }, [getRedirect]); | ||||
| 
 | ||||
|     if (loading) { | ||||
|         return <Loader />; | ||||
|     } | ||||
| 
 | ||||
|     return null; | ||||
| }; | ||||
| @ -2,13 +2,6 @@ | ||||
| 
 | ||||
| exports[`returns all baseRoutes 1`] = ` | ||||
| [ | ||||
|   { | ||||
|     "component": [Function], | ||||
|     "menu": {}, | ||||
|     "path": "/", | ||||
|     "title": "Unleash", | ||||
|     "type": "protected", | ||||
|   }, | ||||
|   { | ||||
|     "component": [Function], | ||||
|     "isStandalone": true, | ||||
|  | ||||
| @ -45,13 +45,6 @@ import { LazyProject } from 'component/project/Project/LazyProject'; | ||||
| import { AdminRedirect } from 'component/admin/AdminRedirect'; | ||||
| 
 | ||||
| export const routes: IRoute[] = [ | ||||
|     { | ||||
|         path: '/', | ||||
|         title: 'Unleash', | ||||
|         component: ProjectListNew, | ||||
|         type: 'protected', | ||||
|         menu: {}, | ||||
|     }, | ||||
|     // Splash
 | ||||
|     { | ||||
|         path: '/splash/:splashId', | ||||
|  | ||||
| @ -28,7 +28,7 @@ const DemoAuth: VFC<IDemoAuthProps> = ({ authDetails, redirect }) => { | ||||
|         try { | ||||
|             await emailAuth(authDetails.path, email); | ||||
|             refetchUser(); | ||||
|             navigate(redirect); | ||||
|             navigate(redirect, { replace: true }); | ||||
|         } catch (error) { | ||||
|             setToastApiError(formatUnknownError(error)); | ||||
|         } | ||||
|  | ||||
| @ -71,7 +71,7 @@ const HostedAuth: VFC<IHostedAuthProps> = ({ authDetails, redirect }) => { | ||||
|         try { | ||||
|             await passwordAuth(authDetails.path, username, password); | ||||
|             refetchUser(); | ||||
|             navigate(redirect); | ||||
|             navigate(redirect, { replace: true }); | ||||
|         } catch (error: any) { | ||||
|             if ( | ||||
|                 error instanceof NotFoundError || | ||||
|  | ||||
| @ -71,7 +71,7 @@ const PasswordAuth: VFC<IPasswordAuthProps> = ({ authDetails, redirect }) => { | ||||
|         try { | ||||
|             await passwordAuth(authDetails.path, username, password); | ||||
|             refetchUser(); | ||||
|             navigate(redirect); | ||||
|             navigate(redirect, { replace: true }); | ||||
|         } catch (error: any) { | ||||
|             if ( | ||||
|                 error instanceof NotFoundError || | ||||
|  | ||||
| @ -27,7 +27,7 @@ const SimpleAuth: VFC<ISimpleAuthProps> = ({ authDetails, redirect }) => { | ||||
|         try { | ||||
|             await emailAuth(authDetails.path, email); | ||||
|             refetchUser(); | ||||
|             navigate(redirect); | ||||
|             navigate(redirect, { replace: true }); | ||||
|         } catch (error) { | ||||
|             setToastApiError(formatUnknownError(error)); | ||||
|         } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user