react-router#useMatch TypeScript Examples
The following examples show how to use
react-router#useMatch.
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: useCharSelectionCallback.tsx From genshin-optimizer with MIT License | 6 votes |
/**
* Basically a history hook to go to the dedicated character page. Will create the character if it doesn't exist.
* @returns
*/
export default function useCharSelectionCallback() {
const { database } = useContext(DatabaseContext)
const navigate = useNavigate()
// Used to maintain the previous tab, if there is one
let { params: { tab = "" } } = useMatch({ path: "/characters/:charKey/:tab", end: false }) ?? { params: { tab: "" } }
const cb = useCallback(
async (characterKey: CharacterKey) => {
const character = database._getChar(characterKey)
let navTab = tab
// Create a new character + weapon, with linking if char isnt in db.
if (!character) {
const newChar = initialCharacter(characterKey)
database.updateChar(newChar)
const characterSheet = await CharacterSheet.get(characterKey)
if (!characterSheet) return
const weapon = defaultInitialWeapon(characterSheet.weaponTypeKey)
const weaponId = database.createWeapon(weapon)
database.setWeaponLocation(weaponId, characterKey)
// If we are navigating to a new character,
// redirect to Overview, regardless of previous tab.
// Trying to enforce a certain UI flow when building new characters
navTab = ""
}
navigate(`/characters/${characterKey}/${navTab}`)
},
[navigate, database, tab],
)
return cb
}
Example #2
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
}
Example #3
Source File: CreateMemberModal.tsx From atlas with GNU General Public License v3.0 | 4 votes |
CreateMemberModal: React.FC<CreateMemberModalProps> = ({ show, selectedAccountAddress }) => {
const { activeAccountId, refetchMemberships, extensionConnected, setActiveUser } = useUser()
const nodeConnectionStatus = useConnectionStatusStore((state) => state.nodeConnectionStatus)
const navigate = useNavigate()
const { pathname } = useLocation()
const isSignIn = useMatch(absoluteRoutes.studio.signIn())
const isStudio = pathname.search(absoluteRoutes.studio.index()) !== -1
const accountIdRef = useRef(activeAccountId)
const [membershipBlock, setMembershipBlock] = useState<number | null>(null)
const [openCreatingMemberDialog, closeCreatingMemberDialog] = useConfirmationModal({
headerIcon: <Loader variant="medium" />,
title: 'Creating membership...',
description:
"Please wait while your membership is being created. Our faucet server will create it for you so you don't need to worry about any fees. This should take about 15 seconds.",
})
const [isCreatingMembership, setIsCreatingMembership] = useState(false)
const [openErrorDialog, closeErrorDialog] = useConfirmationModal()
const { displaySnackbar } = useSnackbar()
const { queryNodeState, error: queryNodeStateError } = useQueryNodeStateSubscription({ skip: !membershipBlock })
// subscription doesn't allow 'onError' callback
useEffect(() => {
if (!queryNodeStateError) return
SentryLogger.error('Failed to subscribe to query node state', 'CreateMemberView', queryNodeStateError)
}, [queryNodeStateError])
const accountSet = !!selectedAccountAddress && !!extensionConnected
const { reset, register, errors, handleSubmit, isValid, getValues, watch } = useCreateEditMemberForm({})
// success
useEffect(() => {
if (!membershipBlock || !queryNodeState || !activeAccountId) {
return
}
if (queryNodeState.indexerHead >= membershipBlock) {
// trigger membership refetch
closeCreatingMemberDialog()
refetchMemberships().then(({ data }) => {
const lastCreatedMembership = data.memberships[data.memberships.length - 1]
if (lastCreatedMembership) {
setActiveUser({ memberId: lastCreatedMembership.id, channelId: null })
}
})
setIsCreatingMembership(false)
reset()
setMembershipBlock(null)
displaySnackbar({
title: 'Your membership has been created',
description: 'Browse, watch, create, collect videos across the platform and have fun!',
iconType: 'success',
})
if (isStudio) {
navigate(isSignIn ? absoluteRoutes.studio.newChannel() : absoluteRoutes.studio.signIn())
} else {
navigate(pathname)
}
}
}, [
activeAccountId,
closeCreatingMemberDialog,
displaySnackbar,
isSignIn,
isStudio,
membershipBlock,
navigate,
pathname,
queryNodeState,
refetchMemberships,
reset,
setActiveUser,
])
const handleCreateMember = handleSubmit(async (data) => {
if (!selectedAccountAddress) {
return
}
try {
setActiveUser({ accountId: selectedAccountAddress })
openCreatingMemberDialog()
setIsCreatingMembership(true)
const { block } = await createNewMember(selectedAccountAddress, data)
setMembershipBlock(block)
} catch (error) {
setActiveUser({ accountId: accountIdRef.current })
closeCreatingMemberDialog()
const errorMessage = (error.isAxiosError && (error as AxiosError).response?.data.error) || 'Unknown error'
openErrorDialog({
iconType: 'error',
title: 'Something went wrong...',
description: `Some unexpected error was encountered. If this persists, our Discord community may be a good place to find some help. Error code: ${errorMessage}`,
secondaryButton: {
text: 'Close',
onClick: () => {
setIsCreatingMembership(false)
closeErrorDialog()
},
},
})
}
})
const handleExitClick = () => {
reset()
navigate({ search: '' })
}
if (queryNodeStateError) {
return <ViewErrorFallback />
}
return (
<StyledDialogModal
title="Create a Joystream membership"
show={show && accountSet && !isCreatingMembership}
dividers
as="form"
onSubmit={handleCreateMember}
onExitClick={handleExitClick}
additionalActionsNode={
<StyledButton disabled={nodeConnectionStatus !== 'connected' || !isValid} type="submit" size="large">
Create membership
</StyledButton>
}
>
<Wrapper>
<Text variant="t200" secondary>
Membership represents you as a member of the Joystream community - it's your on-chain identity. It lets you
interact with the network - create a channel, publish content, issue and trade NFTs. It also lets you to
participate in the platform governance, shaping its future.
</Text>
<StyledAvatar
size="channel-card"
assetUrl={errors.avatar ? undefined : getValues('avatar')}
hasAvatarUploadFailed={!!errors.avatar}
/>
</Wrapper>
<CreateEditMemberInputs register={register} errors={errors} watch={watch} />
</StyledDialogModal>
)
}