Gatsby or Theme UI Link

Date published: 17-Apr-2020
Date modified: 18-Apr-2020
1 min read / 368 words
Author: Paul Scanlon

React
Gatsby
JavaScript
Theme UI

I know this has tripped me up on more than one occasion and if you're using Theme UI components in your Gatsby project it might have caught you out too.

The problem

The problem is that Gatsby and @theme-ui/components both have a component called Link.

First let's look at the Gatsby Link


// some-file.js
import { Link } from "gatsby"
const SomeComponent = () => {
return <Link to="/">Back to home</Link>
}

The Gatsby Link uses a to prop instead of an href, this is because a Gatsby Link is used to navigate around the routes in your blog / site / application.

Now let's look at the Theme UI Link


// some-file.js
import { Link } from "@theme-ui/components"
const SomeComponent = () => {
return <Link href="https://www.paulie.dev">https://www.paulie.dev</Link>
}

The Theme UI Link uses an href attribute which is what you'd normally expect to see on an <a> and it's used to navigate to a URL.

When you look at the import its easy to tell from which library the Link is being imported from but in the usage they look very similar, apart from the difference mentioned above.

We're also presented with a little problem, suppose you want to navigate to a route and link to a URL in the same component. This requires importing and using both the Link from Gatsby and the Link from Theme UI components...


// some-file.js
import { Link } from "gatsby"
import { Link } from "@theme-ui/components"
const SomeComponent = () => {
return (
<>
<Link to="/">Back to home</Link>
<Link href="https://www.paulie.dev">https://www.paulie.dev</Link>
</>
)
}

❌ ... and as you know you can't import two components with the same name.

The next problem is how to style these links. If you're familiar with Theme UI you'll want to use the sx prop 👇


// some-file.js
import { Link } from "gatsby"
import { Link } from "@theme-ui/components"
const SomeComponent = () => {
return (
<>
<Link sx={{ color: "primary" }} to="/">
Back to home
</Link>
<Link sx={{ color: "secondary" }} href="https://www.paulie.dev">
https://www.paulie.dev
</Link>
</>
)
}

... but the Gatsby Link isn't a Theme UI component so it's unable to translate the values passed by the sx prop into CSS styles. Instead it'll pass the sx prop on as an attribute with an odd looking string object thingy.

The rendered DOM node might look like this 👇


<a sx="[object Object]" href="/">
Back to home
</a>

The solution

First off lets change the way we import the Gatsby Link


// some-file.js
import { Link as GatsbyLink } from "gatsby"

No it's easier to determine if we're looking at a Gatsby Link or a Theme UI Link in both the import statement and in the usage.

Great! we've solved one of the problems, but we still want to style these Links using Theme UI.

To achieve this we can cast the Theme UI Link as a GatsbyLink using the as prop ✨


// some-file.js
import { Link as GatsbyLink } from "gatsby"
import { Link } from "@theme-ui/components"
const SomeComponent = () => {
return (
<>
<Link sx={{ color: "primary" }} to="/" as={GatsbyLink}>
Back to home
</Link>
<Link sx={{ color: "secondary" }} href="https://www.paulie.dev">
https://www.paulie.dev
</Link>
</>
)
}

Now we can use the to prop to navigate around our blog / site / application and we can access all that Theme UI goodness using the sx prop.

Pretty sweet ay!



If you've enjoyed this post I'd love to hear from you @pauliescanlon