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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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&apos;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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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&apos;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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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
}