react-router-dom#useNavigate TypeScript Examples
The following examples show how to use
react-router-dom#useNavigate.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: login.tsx From master-frontend-lemoncode with MIT License | 9 votes |
LoginPage: React.FC = () => {
const navigate = useNavigate();
const handleNavigation = () => {
navigate("/list");
};
return (
<>
<h2>Hello from login page</h2>
<button onClick={handleNavigation}>Login</button>
</>
);
}
Example #2
Source File: hooks.ts From your_spotify with GNU General Public License v3.0 | 7 votes |
export function useNavigateAndSearch() {
const navigate = useNavigate();
const [query] = useSearchParams();
return useCallback(
(url: string, params: Record<string, string | undefined>) => {
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined) {
query.set(key, value);
}
});
navigate(`${url}?${query.toString()}`);
},
[navigate, query],
);
}
Example #3
Source File: util.ts From backstage with Apache License 2.0 | 7 votes |
useNavigateToQuery = () => {
const searchRoute = useRouteRef(rootRouteRef);
const navigate = useNavigate();
return useCallback(
({ query }: { query: string }): void => {
const queryString = qs.stringify({ query }, { addQueryPrefix: true });
navigate(`${searchRoute()}${queryString}`);
},
[navigate, searchRoute],
);
}
Example #4
Source File: bluna.convert.tsx From anchor-web-app with Apache License 2.0 | 6 votes |
function Component({ className }: UIElementProps) {
const navigate = useNavigate();
const match = useMatch({ path: '/basset/bluna/:page', end: true });
const tab = useMemo<Item | undefined>(() => {
return tabItems.find(({ value }) => value === match?.params.page);
}, [match?.params.page]);
const tabChange = useCallback(
(nextTab: Item) => {
navigate(`/basset/bluna/${nextTab.value}`);
},
[navigate],
);
return (
<CenteredLayout maxWidth={800} className={className}>
<TitleContainer>
<PageTitle title="MINT & BURN" />
</TitleContainer>
<Tab
className="tab"
items={tabItems}
selectedItem={tab ?? tabItems[0]}
onChange={tabChange}
labelFunction={({ label }) => label}
keyFunction={({ value }) => value}
tooltipFunction={({ tooltip }) => tooltip}
/>
<Outlet />
</CenteredLayout>
);
}
Example #5
Source File: index.tsx From shippo with MIT License | 6 votes |
Home = () => {
const history = useNavigate()
const location = useLocation()
console.log(location)
const [selectedTab, setSelectedTab] = useState(
tabBarItems.find((item) => item.path === location.pathname)!.path
)
const onPress = (activeKey: string) => {
setSelectedTab(activeKey)
const path = tabBarItems.find((item) => item.path === activeKey)?.path
path && history(path)
}
return (
<Container direction="vertical">
<Main>
<Outlet />
</Main>
<Footer height="50px" style={{ backgroundColor: '#fff' }}>
<StyledTabBar activeKey={selectedTab} onChange={(activeKey) => onPress(activeKey)}>
{tabBarItems.map((item) => (
<TabBar.Item title={item.title} key={item.path} icon={<Icon type={item.icon} />} />
))}
</StyledTabBar>
</Footer>
</Container>
)
}
Example #6
Source File: ViewErrorFallback.tsx From atlas with GNU General Public License v3.0 | 6 votes |
ViewErrorFallback: React.FC<ViewErrorFallbackProps> = ({ onResetClick }) => {
const navigate = useNavigate()
const handleResetClick = () => {
if (onResetClick) {
onResetClick()
} else {
navigate(absoluteRoutes.viewer.index())
}
}
return (
<Container>
<AnimatedError />
<Message>
<Header variant="h600">Oops! An error occurred.</Header>
<Text variant="t300" secondary>
Something bad happened and the app broke. This has been logged and we'll try to resolve it as soon as
possible. You can find support in our Discord community.
</Text>
</Message>
<ButtonsContainer>
<Button to={JOYSTREAM_DISCORD_URL} variant="secondary">
Open Discord
</Button>
<Button onClick={handleResetClick}>Return to home page</Button>
</ButtonsContainer>
</Container>
)
}
Example #7
Source File: login.tsx From master-frontend-lemoncode with MIT License | 6 votes |
LoginPage: React.FC = () => {
const navigate = useNavigate();
const [username, setUsername] = React.useState("");
const [password, setPassword] = React.useState("");
const handleNavigation = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (username === "admin" && password === "test") {
navigate("/list");
} else {
alert("User / password not valid, psst... admin / test");
}
};
return (
<form onSubmit={handleNavigation}>
<h2>Hello from login page</h2>
<div>
<div>
<label>Username: </label>
<input
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div>
<label>Password: </label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
</div>
<button type="submit">login</button>
</form>
);
}
Example #8
Source File: ProjectPage.tsx From frontend with Apache License 2.0 | 6 votes |
ProjectPage = () => {
const classes = useStyles();
const { projectId } = useParams<{ projectId: string }>();
const navigate = useNavigate();
const helpDispatch = useHelpDispatch();
useEffect(() => {
setHelpSteps(helpDispatch, PROJECT_PAGE_STEPS);
});
return (
<React.Fragment>
<Grid container className={classes.root}>
<Grid item xs={3} className={classes.root}>
<Box height="9%" id={LOCATOR_PROJECT_PAGE_SELECT_PROJECT}>
<ProjectSelect
projectId={projectId}
onProjectSelect={(id) => navigate(buildProjectPageUrl(id))}
/>
</Box>
<Box height="91%" id={LOCATOR_PROJECT_PAGE_BUILD_LIST}>
<BuildList />
</Box>
</Grid>
<Grid item xs={9} className={classes.root}>
<Box height="15%">
<BuildDetails />
</Box>
<Box height="85%" id={LOCATOR_PROJECT_PAGE_TEST_RUN_LIST}>
<TestRunList />
</Box>
</Grid>
</Grid>
<TestDetailsDialog />
</React.Fragment>
);
}
Example #9
Source File: PrivateRoute.tsx From your_spotify with GNU General Public License v3.0 | 6 votes |
export default function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
const user = useSelector(selectUser);
const accounts = useSelector(selectAccounts);
const loaded = useSelector(selectLoaded);
const navigate = useNavigate();
useEffect(() => {
if (loaded && !user) {
navigate('/login');
}
}, [loaded, navigate, user]);
if (!loaded) {
return <CircularProgress />;
}
if (!user || !accounts || accounts.length === 0) {
return <div />;
}
return children;
}
Example #10
Source File: index.tsx From auth0-react with MIT License | 6 votes |
Auth0ProviderWithRedirectCallback = ({
children,
...props
}: PropsWithChildren<Auth0ProviderOptions>) => {
const navigate = useNavigate();
const onRedirectCallback = (appState?: AppState) => {
navigate((appState && appState.returnTo) || window.location.pathname);
};
return (
<Auth0Provider onRedirectCallback={onRedirectCallback} {...props}>
{children}
</Auth0Provider>
);
}
Example #11
Source File: SidebarSearch.tsx From backstage with Apache License 2.0 | 6 votes |
SidebarSearch = (props: SidebarSearchProps) => {
const searchRoute = useRouteRef(rootRouteRef);
const { focusContent } = useContent();
const navigate = useNavigate();
const handleSearch = useCallback(
(query: string): void => {
const queryString = qs.stringify({ query }, { addQueryPrefix: true });
focusContent();
navigate(`${searchRoute()}${queryString}`);
},
[focusContent, navigate, searchRoute],
);
return (
<SidebarSearchField
icon={props.icon}
onSearch={handleSearch}
to="/search"
/>
);
}
Example #12
Source File: auth.tsx From frontend with BSD 3-Clause "New" or "Revised" License | 6 votes |
RequireAuth: React.FC<RequireAuthProps> = ({ groupRequired, redirectUrlWhenUnauthorized, children }) => {
const { user, redirectToLogin } = useUser()
const navigate = useNavigate()
if (!user) {
redirectToLogin()
return null
}
if (!groupRequired.includes(user?.userGroup)) {
navigate(redirectUrlWhenUnauthorized, { replace: true })
return null
}
return <>{children}</>
}
Example #13
Source File: AddMoodFab.tsx From moodtracker with MIT License | 6 votes |
export default function AddMoodFab({ hide }: Props) {
const { pathname } = useLocation();
const navigate = useNavigate();
return (
<Fab
hide={hide || PATHS_TO_HIDE_ON.some((path) => pathname.startsWith(path))}
onClick={() => navigate(`/add`)}
>
<Icon name="plus" size="4" />
Add mood
</Fab>
);
}
Example #14
Source File: deepLink.ts From celo-web-wallet with MIT License | 6 votes |
export function useDeepLinkHandler() {
const [searchParams] = useSearchParams()
const dispatch = useAppDispatch()
const navigate = useNavigate()
const location = useLocation()
useEffect(() => {
// WalletConnect URI
const path = trimSlashes(location.pathname)
if (path === 'wc' && searchParams.has('uri')) {
logger.info('WalletConnect URI found in URL')
const uri = decodeURIComponent(searchParams.get('uri') || '')
const validation = validateWalletConnectForm({ uri })
if (validation.isValid) dispatch(initializeWcClient(uri))
// For now, the app doesn't use search params for anything else
// so it's safe to clear them. This may need to change eventually
// Note, not using setSearchParams here because it leaves a ? in the url
navigate('/', { replace: true })
}
}, [])
}
Example #15
Source File: Header.tsx From nodestatus with MIT License | 6 votes |
Header: FC<Props> = props => {
const navigate = useNavigate();
const { isCollapsed, toggleCollapsed } = props.collapsed;
const menu = (
<Menu
items={[
{
key: 'logout',
label: 'Logout',
icon: <LogoutOutlined className="mr-2 align-middle" />,
className: 'align-middle'
}
]}
onClick={({ key }) => {
if (key === 'logout') {
localStorage.removeItem('token');
navigate('/login');
}
}}
/>
);
return (
<div className="h-full flex items-center justify-between">
{React.createElement(isCollapsed ? MenuUnfoldOutlined : MenuFoldOutlined, {
className: 'text-2xl',
onClick: toggleCollapsed
})}
<Dropdown overlay={menu} placement="bottom">
<Avatar size={40} icon={<UserOutlined />} />
</Dropdown>
</div>
);
}
Example #16
Source File: Back.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 6 votes |
function Back(): JSX.Element {
const { t } = useTranslation('common');
const navigate = useNavigate();
const darkMode = useStore(useCallback((state) => state.darkMode, []));
const handleBack = () => {
navigate(-1);
};
return (
<Button className={styles.button} onClick={handleBack} inverted={darkMode} type="button">
<Icon className={styles.icon} name="arrow left" />
<span className={styles.text}>{t('back')}</span>
</Button>
);
}
Example #17
Source File: HistoryHeader.tsx From bee-dashboard with BSD 3-Clause "New" or "Revised" License | 6 votes |
export function HistoryHeader({ children }: Props): ReactElement {
const classes = useStyles()
const navigate = useNavigate()
function goBack() {
navigate(-1)
}
return (
<Box mb={4}>
<Grid container direction="row">
<Box mr={2}>
<div className={classes.pressable} onClick={goBack}>
<ArrowBack className={classes.icon} />
</div>
</Box>
<Typography variant="h1">{children}</Typography>
</Grid>
</Box>
)
}
Example #18
Source File: Page404.tsx From gateway-ui with BSD 3-Clause "New" or "Revised" License | 6 votes |
Page404 = (): ReactElement => {
const classes = useStyles()
const navigate = useNavigate()
return (
<Layout
top={[
<Header key="top1">
<Logo />
</Header>,
]}
center={[
<Paper key="center" square elevation={0} className={classes.root}>
<AlertOctagon size={48} strokeWidth={0.5} />
<Typography variant="subtitle1">{text.page404.header}</Typography>
<Typography variant="body2">{text.page404.description}</Typography>
</Paper>,
]}
bottom={[
<Footer key="bottom">
<Button
variant="contained"
className={classes.button}
onClick={() => {
navigate(ROUTES.LANDING_PAGE)
}}
size="large"
>
<ArrowLeft strokeWidth={1} />
{text.page404.goBackAction}
<ArrowLeft style={{ opacity: 0 }} />
</Button>
</Footer>,
]}
/>
)
}
Example #19
Source File: index.tsx From genshin-optimizer with MIT License | 6 votes |
export default function CharacterDisplay() {
const navigate = useNavigate();
let { characterKey } = useParams<{ characterKey?: CharacterKey }>();
const invalidKey = !allCharacterKeys.includes(characterKey as any ?? "")
if (invalidKey)
return <Navigate to="/characters" />
return <Box my={1} display="flex" flexDirection="column" gap={1}>
{characterKey && <Suspense fallback={<Skeleton variant="rectangular" width="100%" height={1000} />}>
<CharacterDisplayCard characterKey={characterKey} onClose={() => navigate("/characters")} />
</Suspense>}
</Box>
}
Example #20
Source File: BackButton.tsx From gear-js with GNU General Public License v3.0 | 6 votes |
BackButton = (props: Omit<ButtonProps, OmittedProps>) => {
const navigate = useNavigate();
const handleClick = () => {
navigate(-1);
};
return <Button icon={arrow} color="transparent" onClick={handleClick} {...props} />;
}
Example #21
Source File: index.tsx From pintora with MIT License | 6 votes |
AppSidebar = ({}: Props) => {
const navigate = useNavigate()
const currentLocation = useLocation()
const cls = classnames('AppSidebar bg-warmGray-100 flex flex-col items-center')
const handleClick = useCallback((item: SidebarItem) => {
navigate(item.name)
}, [])
return (
<div className={cls}>
{SIDEBAR_ICONS.map(item => {
const itemCls = classnames('AppSidebar__item btn btn-ghost btn-square mb-2', {
'btn-active': `/${item.name}` === currentLocation.pathname,
})
return (
<div key={item.name} title={item.label} className={itemCls} onClick={() => handleClick(item)}>
<i className="iconify-inline" data-icon={item.icon} data-width="26"></i>
<br />
</div>
)
})}
</div>
)
}
Example #22
Source File: index.tsx From ant-simple-draw with MIT License | 6 votes |
PageError = memo(function PageError() {
const navigate = useNavigate();
const backs = () => {
navigate('/');
};
return (
<Result
status="404"
title="404"
subTitle="sorry,页面没有找到,请点击下面返回按钮,再试一次"
extra={
<Button type="primary" onClick={backs}>
返回主页
</Button>
}
/>
);
})
Example #23
Source File: TitleBar.tsx From mysterium-vpn-desktop with MIT License | 6 votes |
TitleBar: React.FC = observer(function TitleBar() {
const { navigation, identity, isWindows, isLinux } = useStores()
const navigate = useNavigate()
const location = useLocation()
const isHomeActive = location.pathname.startsWith(locations.consumer)
const isSettingsActive = location.pathname.startsWith(locations.settings)
const isHelpActive = location.pathname.startsWith(locations.help)
const isWalletActive = location.pathname.startsWith(locations.wallet)
return (
<Container>
<NavigationButton active={isHomeActive} onClick={() => !isHomeActive && navigation.goHome()}>
<FontAwesomeIcon icon={faHome} />
</NavigationButton>
<NavigationButton
active={isSettingsActive}
onClick={() => !isSettingsActive && navigate(locations.settings)}
>
Settings
</NavigationButton>
<NavigationButton active={isHelpActive} onClick={() => !isHelpActive && navigate(locations.help)}>
Help
</NavigationButton>
<Location>
<IP />
<ProtectionStatus />
</Location>
<WalletButton active={isWalletActive} onClick={() => !isWalletActive && navigate(locations.wallet)}>
<Money>
<IconMystToken color={isWalletActive ? "#fff" : greyBlue1} />
<span>
{displayTokens2(identity.identity?.balanceTokens)} {Currency.MYST}
</span>
</Money>
</WalletButton>
{isWindows && <WindowButtonsWindows />}
{isLinux && <WindowButtonsLinux />}
</Container>
)
})
Example #24
Source File: SwaggerToolboxPage.tsx From one-platform with MIT License | 5 votes |
SwaggerToolboxPage = (): JSX.Element => {
const { envSlug } = useParams();
const navigate = useNavigate();
const { pathname } = useLocation();
const { isLoading, data: schemaData } = useGetApiSchemaFile({ envSlug });
const [isDecodingFile, setIsDecodingFile] = useToggle();
const schema = schemaData?.fetchAPISchema?.schema;
const namespaceSlug = schemaData?.fetchAPISchema?.namespaceSlug;
const file = schemaData?.fetchAPISchema?.file;
useRegisterRecentVisit({
isLoading: isLoading || isDecodingFile,
log: useMemo(
() => ({
title: schema?.name || '',
tool: 'swagger',
url: pathname,
id: namespaceSlug as string,
envSlug: envSlug as string,
}),
[pathname, namespaceSlug, schema?.name, envSlug]
),
onRemoveId: namespaceSlug,
});
const schemaFile = useMemo(() => {
if (file) {
try {
setIsDecodingFile.on();
const data = yaml.load(window.atob(file));
return data as object;
} catch (error) {
window.OpNotification.danger({
subject: 'Failed to parse file!!',
});
} finally {
setIsDecodingFile.off();
}
}
return '';
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [file]);
if (isLoading || isDecodingFile) {
return (
<Bullseye>
<Spinner size="xl" />
</Bullseye>
);
}
if (!file) {
return (
<Bullseye>
<EmptyState>
<EmptyStateIcon icon={CubeIcon} />
<Title headingLevel="h4" size="lg">
Sorry, Couldn't find this API
</Title>
<Button variant="primary" onClick={() => navigate('/apis')}>
Go Back
</Button>
</EmptyState>
</Bullseye>
);
}
return <SwaggerUI spec={schemaFile} tryItOutEnabled />;
}
Example #25
Source File: TransactionWidget.tsx From anchor-web-app with Apache License 2.0 | 5 votes |
TransactionWidgetBase = (props: UIElementProps & { color?: string }) => {
const theme = useTheme();
const { className, color = theme.header.textColor } = props;
const [open, setOpen] = useState(false);
const { backgroundTransactions } = useBackgroundTransactions();
const {
target: { chain },
} = useDeploymentTarget();
const navigate = useNavigate();
const restoreTx = useCallback(() => {
setOpen(false);
navigate('/bridge/restore');
}, [navigate, setOpen]);
if (backgroundTransactions.length === 0 || chain === Chain.Terra) {
return null;
}
return (
<ClickAwayListener onClickAway={() => setOpen(false)}>
<div className={className}>
<TransactionButton
color={color}
backgroundTransactions={backgroundTransactions}
onClick={() => setOpen((v) => !v)}
closeWidget={() => setOpen(false)}
/>
{open && (
<DropdownContainer className="transaction-dropdown">
<DropdownBox>
<TransactionList
backgroundTransactions={backgroundTransactions}
onClose={() => setOpen((v) => !v)}
footer={
<div className="restore-tx">
<div>Having transaction issues?</div>
<BorderButton onClick={restoreTx}>
Restore transaction
</BorderButton>
</div>
}
/>
</DropdownBox>
</DropdownContainer>
)}
</div>
</ClickAwayListener>
);
}
Example #26
Source File: useUnsavedChangesDialog.tsx From firecms with MIT License | 5 votes |
export function useNavigationUnsavedChangesDialog(when: boolean, onSuccess: () => void):
{
navigationWasBlocked: boolean,
handleCancel: () => void,
handleOk: () => void
} {
const [nextLocation, setNextLocation] = React.useState<any | undefined>();
const { navigator } = React.useContext(UNSAFE_NavigationContext);
const navigate = useNavigate();
const handleCancel = () => {
setNextLocation(undefined);
};
const handleOk = () => {
onSuccess();
setNextLocation(undefined);
navigate(-1);
};
const blocker: Blocker = useCallback(({ action, location: nextLocation, retry }) => {
switch (action) {
case "REPLACE": {
retry();
return;
}
case "POP": {
setNextLocation(nextLocation);
}
}
}, []);
React.useEffect(() => {
if (!when) return;
if (nextLocation) return;
if (!("block" in navigator)) return;
const unblock = (navigator as any).block((tx: Transition) => {
const autoUnblockingTx = {
...tx,
retry() {
unblock();
tx.retry();
}
};
blocker(autoUnblockingTx);
});
return unblock;
}, [navigator, blocker, when, nextLocation]);
return { navigationWasBlocked: Boolean(nextLocation), handleCancel, handleOk };
}
Example #27
Source File: root-router.tsx From shippo with MIT License | 5 votes |
Component: React.FC<RootRouteProps> = ({ result }) => {
const history = useNavigate()
const location = useLocation()
useMount(() => {
console.log(result)
const resource = result[0].data.resource
localStorage.setItem('__PASSPORT', resource.passport)
if (resource.uid > 0) {
message.success(`已经登录,UID为${resource.uid}`)
if (location.pathname.startsWith('/passport')) {
history('/')
}
} else {
message.error('没有登录')
history('/passport')
}
})
return (
<Routes>
<Route path="/passport" element={<Passport />}>
<Route path="" element={<Page_passport />}></Route>
</Route>
<Route path="/transform" element={<Transform />}></Route>
<Route path="/dashboard" element={<Home />}>
<Route path="" element={withLoading(lazy(() => import('~/pages/dashboard')))}></Route>
</Route>
<Route path="/users" element={<Home />}>
<Route path="" element={withLoading(lazy(() => import('~/pages/users')))}></Route>
</Route>
<Route path="/temp/*" element={<Home />}>
<Route
path="temp_trade_20220108"
element={withLoading(lazy(() => import('~/pages/temp/temp_trade_20220108')))}
></Route>
</Route>
<Route path="/permission/*" element={<Home />}>
<Route
path="role"
element={withLoading(lazy(() => import('~/pages/permission/role')))}
></Route>
<Route
path="access"
element={withLoading(lazy(() => import('~/pages/permission/access')))}
></Route>
<Route
path="policy"
element={withLoading(lazy(() => import('~/pages/permission/policy')))}
></Route>
</Route>
<Route path="*" element={<Navigate to="/dashboard" replace />}></Route>
</Routes>
)
}
Example #28
Source File: meet.tsx From video-chat with MIT License | 5 votes |
export default function Meet(){
const navigate = useNavigate()
const myVideoRef = useRef<any>()
const otherUserRef = useRef<any>()
const socketRef = useRef<Socket>()
const { currentCall, userId } = useStore()
const handleHangUp = () => {
currentCall.reset()
socketRef.current?.emit("hang-up", { to: currentCall.userId, from: userId })
socketRef.current?.disconnect()
navigate('/')
}
useEffect(() => {
if (!otherUserRef.current || !myVideoRef.current) return
otherUserRef.current.srcObject = currentCall.stream
myVideoRef.current.srcObject = currentCall.myStream
}, [currentCall])
useEffect(() => {
socketRef.current = io("http://localhost:8000");
socketRef.current.on("hanging-up", (data) => {
if(data.from === currentCall.userId){
currentCall.reset()
navigate('/')
}
})
return () => handleHangUp()
}, [])
return(
<Page>
<Box
as="video"
playsInline
muted
ref={myVideoRef}
autoPlay
maxW="300px"
minW="150px"
borderRadius="16px"
m="4"
/>
<Box
as="video"
playsInline
muted
ref={otherUserRef}
autoPlay
maxW="300px"
minW="150px"
borderRadius="16px"
m="4"
/>
<Box as="span" border="1px solid red" p="4" borderRadius="rounded">
<ImPhoneHangUp color="red" fontSize="32px" onClick={handleHangUp} cursor="pointer" />
</Box>
</Page>
)
}
Example #29
Source File: hooks.ts From atlas with GNU General Public License v3.0 | 5 votes |
useVideoWorkspaceRouting = (): Location => {
const navigate = useNavigate()
const location = useLocation()
const locationState = location.state as RoutingState
const [cachedLocation, setCachedLocation] = useState<Location>()
const videoWorkspaceMatch = useMatch(WORKSPACE_MATCH)
const { isWorkspaceOpen, setIsWorkspaceOpen } = useVideoWorkspace()
const [cachedIsWorkspaceOpen, setCachedIsWorkspaceOpen] = useState(false)
useEffect(() => {
if (location === cachedLocation) {
return
}
setCachedLocation(location)
if (videoWorkspaceMatch && !isWorkspaceOpen) {
// route changed to video edit
const state: RoutingState = {
overlaidLocation: cachedLocation ?? defaultLocation,
}
navigate(location, { replace: true, state })
setIsWorkspaceOpen(true)
}
}, [location, cachedLocation, videoWorkspaceMatch, navigate, isWorkspaceOpen, setIsWorkspaceOpen])
useEffect(() => {
if (isWorkspaceOpen === cachedIsWorkspaceOpen) {
return
}
setCachedIsWorkspaceOpen(isWorkspaceOpen)
if (!isWorkspaceOpen) {
// restore the old location when videoWorkspace was closed
const oldLocation = locationState?.overlaidLocation ?? absoluteRoutes.studio.index()
navigate(oldLocation)
}
if (isWorkspaceOpen && !videoWorkspaceMatch) {
// isWorkspaceOpen changed without the route change, change URL and save current location
const state: RoutingState = {
overlaidLocation: location,
}
navigate(absoluteRoutes.studio.videoWorkspace(), { state: state })
}
}, [cachedIsWorkspaceOpen, isWorkspaceOpen, location, locationState, navigate, videoWorkspaceMatch])
if (videoWorkspaceMatch) {
return locationState?.overlaidLocation ?? cachedLocation ?? defaultLocation
}
return location
}