mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Fix/redirect woes (#2899)
This PR fixes two problems: (1) The initial redirect put us into an infinite loop when redirecting, because trying to go back to the root would always trigger the initial redirect component. Throwing you back to project screen. (2) Using UI config in the useLastViewedProject to get the basePath introduced a race condition where you needed data from the uiConfig in order to fetch the correct key from local storage. The fix here was to use the basePath coded into the HTML file, so we can synchronously retrieve the correct key at startup. Co-authored-by: kwasniew <kwasniewski.mateusz@gmail.com>
This commit is contained in:
		
							parent
							
								
									801e31dc4e
								
							
						
					
					
						commit
						1f6db91fde
					
				| @ -14,7 +14,8 @@ | ||||
|     "start": "vite", | ||||
|     "start:prod": "vite build && vite preview", | ||||
|     "start:sandbox": "UNLEASH_API=https://sandbox.getunleash.io/ospro yarn run start", | ||||
|     "start:enterprise": "UNLEASH_API=https://unleash.herokuapp.com yarn run start", | ||||
|     "start:demo2": "UNLEASH_API=https://sandbox.getunleash.io/ UNLEASH_BASE_PATH=/demo2/ yarn run start", | ||||
|     "start:enterprise": "UNLEASH_API=https://unleash.herokuapp.com VITE_TEST_REDIRECT=true yarn run start", | ||||
|     "start:demo": "UNLEASH_BASE_PATH=/demo/ yarn start", | ||||
|     "test": "tsc && vitest run", | ||||
|     "test:snapshot": "yarn test -u", | ||||
| @ -111,7 +112,9 @@ | ||||
|   "resolutions": { | ||||
|     "@codemirror/state": "6.2.0", | ||||
|     "@xmldom/xmldom": "^0.8.4", | ||||
|     "json5": "^2.2.2" | ||||
|     "json5": "^2.2.2", | ||||
|     "@types/react": "17.0.52", | ||||
|     "@types/react-dom": "17.0.18" | ||||
|   }, | ||||
|   "jest": { | ||||
|     "moduleNameMapper": { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { Suspense, useCallback, useEffect, useState } from 'react'; | ||||
| import { Navigate, Route, Routes } from 'react-router-dom'; | ||||
| import { Suspense, useCallback, useEffect, useState, useRef } from 'react'; | ||||
| import { Route, Routes, useNavigate } from 'react-router-dom'; | ||||
| import { ErrorBoundary } from 'react-error-boundary'; | ||||
| import { Error } from 'component/layout/Error/Error'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| @ -24,9 +24,10 @@ import { styled } from '@mui/material'; | ||||
| const InitialRedirect = () => { | ||||
|     const { lastViewed } = useLastViewedProject(); | ||||
|     const { projects, loading } = useProjects(); | ||||
|     const navigate = useNavigate(); | ||||
|     const ref = useRef<{ redirected: boolean }>({ redirected: false }); | ||||
| 
 | ||||
|     const [redirectTo, setRedirectTo] = useState<string | undefined>(); | ||||
| 
 | ||||
|     // Redirect based on project and last viewed
 | ||||
|     const getRedirect = useCallback(() => { | ||||
|         if (projects && lastViewed) { | ||||
|             return `/projects/${lastViewed}`; | ||||
| @ -39,17 +40,22 @@ const InitialRedirect = () => { | ||||
|         return '/projects'; | ||||
|     }, [lastViewed, projects]); | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         if (!loading) { | ||||
|             setRedirectTo(getRedirect()); | ||||
|         } | ||||
|     }, [loading, getRedirect]); | ||||
|     const redirect = () => { | ||||
|         ref.current = { redirected: true }; | ||||
|         navigate(getRedirect(), { replace: true }); | ||||
|     }; | ||||
| 
 | ||||
|     if (loading || !redirectTo) { | ||||
|     useEffect(() => { | ||||
|         if (ref.current?.redirected === true) return; | ||||
| 
 | ||||
|         redirect(); | ||||
|     }, [getRedirect]); | ||||
| 
 | ||||
|     if (loading) { | ||||
|         return <Loader />; | ||||
|     } | ||||
| 
 | ||||
|     return <Navigate to={redirectTo} />; | ||||
|     return <></>; | ||||
| }; | ||||
| 
 | ||||
| const StyledContainer = styled('div')(() => ({ | ||||
| @ -109,16 +115,25 @@ 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" /> | ||||
| 
 | ||||
|                                         <SplashPageRedirect /> | ||||
|                                     </StyledContainer> | ||||
|                                 </> | ||||
|  | ||||
| @ -2,6 +2,13 @@ | ||||
| 
 | ||||
| exports[`returns all baseRoutes 1`] = ` | ||||
| [ | ||||
|   { | ||||
|     "component": [Function], | ||||
|     "menu": {}, | ||||
|     "path": "/", | ||||
|     "title": "Unleash", | ||||
|     "type": "protected", | ||||
|   }, | ||||
|   { | ||||
|     "component": [Function], | ||||
|     "isStandalone": true, | ||||
|  | ||||
| @ -45,6 +45,13 @@ 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', | ||||
|  | ||||
| @ -1,10 +1,9 @@ | ||||
| import { useEffect, useState } from 'react'; | ||||
| import { getLocalStorageItem, setLocalStorageItem } from '../utils/storage'; | ||||
| import useUiConfig from './api/getters/useUiConfig/useUiConfig'; | ||||
| import { basePath } from 'utils/formatPath'; | ||||
| 
 | ||||
| export const useLastViewedProject = () => { | ||||
|     const { uiConfig } = useUiConfig(); | ||||
|     const key = `${uiConfig.baseUriPath}:unleash-lastViewedProject`; | ||||
|     const key = `${basePath}:unleash-lastViewedProject`; | ||||
| 
 | ||||
|     const [lastViewed, setLastViewed] = useState(() => { | ||||
|         return getLocalStorageItem(key); | ||||
|  | ||||
							
								
								
									
										4020
									
								
								frontend/yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										4020
									
								
								frontend/yarn.lock
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user