go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/test_verdict/legacy/invocation_page/invocation_default_tab.tsx (about) 1 // Copyright 2023 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import { useEffect } from 'react'; 16 import { useLocation, useNavigate } from 'react-router-dom'; 17 18 import { RecoverableErrorBoundary } from '@/common/components/error_handling'; 19 20 export function InvocationDefaultTab() { 21 const { pathname, search, hash } = useLocation(); 22 const navigate = useNavigate(); 23 24 // Remove any trailing '/' so the new URL won't contain '//'. 25 const basePath = pathname.replace(/\/*$/, ''); 26 const newUrl = `${basePath}/test-results${search}${hash}`; 27 28 useEffect( 29 () => navigate(newUrl, { replace: true }), 30 // The react-router router implementation could trigger URL related updates 31 // (e.g. search query update) before unmounting the component and 32 // redirecting users to the new component. 33 // This may cause infinite loops if the dependency isn't specified. 34 [navigate, newUrl], 35 ); 36 37 return <></>; 38 } 39 40 export const element = ( 41 // See the documentation for `<LoginPage />` for why we handle error this way. 42 <RecoverableErrorBoundary key="default"> 43 <InvocationDefaultTab /> 44 </RecoverableErrorBoundary> 45 );