While repeating yourself can be acceptable in many situations, you might find that you do it too often. At times, you may want to create cross-cutting components with additional behavior or styles. You might also consider using third-party libraries in combination with TanStack Router’s type safety.
createLink
for cross-cutting concernscreateLink
creates a custom Link
component with the same type parameters as Link
. This means you can create your own component which provides the same type safety and typescript performance as Link
.
If you want to create a basic custom link component, you can do so with the following:
import * as React from 'react'import { createLink, LinkComponent } from '@tanstack/react-router'
interface BasicLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> { // Add any additional props you want to pass to the anchor element}
const BasicLinkComponent = React.forwardRef<HTMLAnchorElement, BasicLinkProps>( (props, ref) => { return ( <a ref={ref} {...props} className={'block px-3 py-2 text-blue-700'} /> ) },)
const CreatedLinkComponent = createLink(BasicLinkComponent)
export const CustomLink: LinkComponent<typeof BasicLinkComponent> = (props) => { return <CreatedLinkComponent preload={'intent'} {...props} />}
You can then use your newly created Link
component as any other Link
<CustomLink to={'/dashboard/invoices/$invoiceId'} params={{ invoiceId: 0 }} />
createLink
with third party librariesReact Aria Components’
Link component does not support the standard onMouseEnter
and onMouseLeave
events.
Therefore, you cannot use it directly with TanStack Router’s preload (intent)
prop.
Explanation for this can be found here:
It is possible to work around this by using the useLink hook from React Aria Hooks with a standard anchor element.
import * as React from 'react'import { createLink, LinkComponent } from '@tanstack/react-router'import { mergeProps, useFocusRing, useHover, useLink, useObjectRef,} from 'react-aria'import type { AriaLinkOptions } from 'react-aria'
interface RACLinkProps extends Omit<AriaLinkOptions, 'href'> { children?: React.ReactNode}
const RACLinkComponent = React.forwardRef<HTMLAnchorElement, RACLinkProps>( (props, forwardedRef) => { const ref = useObjectRef(forwardedRef)
const { isPressed, linkProps } = useLink(props, ref) const { isHovered, hoverProps } = useHover(props) const { isFocusVisible, isFocused, focusProps } = useFocusRing(props)
return ( <a {...mergeProps(linkProps, hoverProps, focusProps, props)} ref={ref} data-hovered={isHovered || undefined} data-pressed={isPressed || undefined} data-focus-visible={isFocusVisible || undefined} data-focused={isFocused || undefined} /> ) },)
const CreatedLinkComponent = createLink(RACLinkComponent)
export const CustomLink: LinkComponent<typeof RACLinkComponent> = (props) => { return <CreatedLinkComponent preload={'intent'} {...props} />}
import * as React from 'react'import { createLink, LinkComponent } from '@tanstack/react-router'import { Link } from '@chakra-ui/react'
interface ChakraLinkProps extends Omit<React.ComponentPropsWithoutRef<typeof Link>, 'href'> { // Add any additional props you want to pass to the link}
const ChakraLinkComponent = React.forwardRef< HTMLAnchorElement, ChakraLinkProps>((props, ref) => { return <Link ref={ref} {...props} />})
const CreatedLinkComponent = createLink(ChakraLinkComponent)
export const CustomLink: LinkComponent<typeof ChakraLinkComponent> = ( props,) => { return ( <CreatedLinkComponent textDecoration={'underline'} _hover={{ textDecoration: 'none' }} _focus={{ textDecoration: 'none' }} preload={'intent'} {...props} /> )}
import * as React from 'react'import { createLink, LinkComponent } from '@tanstack/react-router'import { Button, ButtonProps } from '@mui/material'
interface MUILinkProps extends Omit<ButtonProps, 'href'> { // Add any additional props you want to pass to the button}
const MUILinkComponent = React.forwardRef<HTMLAnchorElement, MUILinkProps>( (props, ref) => { return <Button component={'a'} ref={ref} {...props} /> },)
const CreatedLinkComponent = createLink(MUILinkComponent)
export const CustomLink: LinkComponent<typeof MUILinkComponent> = (props) => { return <CreatedLinkComponent preload={'intent'} {...props} />}
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.