Gatsby: Link to static html is not working

Created on 15 Nov 2017  路  17Comments  路  Source: gatsbyjs/gatsby

Hello,

I'd like to create a link to a static html file but the link is not working.

The reason that I want to do is that I want to use netlify-cms for my gatsby blog. It uses a static html page to launch. The static files are located in /static/admin/ in gatsby project.

Assume that the site url is https://www.site.com.
Then, I can access the admin page with this url: https://www.site.com/admin/.

Now I want to create a link in my gatsby blog to that admin page. I will link it using relative path: '/admin/'

It looks something like this:

class Page extends React.Components {
  render() {
    return (
      <a href="/admin/">Link to admin page</a>
    );
  }
}

If I click the link which is rendered from that code, I can see 404 page.
The console says that: A page wasn't found for "/admin/"
The console message is written from here.

Can I do some schemes to bypass this happening?

question or discussion

Most helpful comment

I've been doing a little Link component that composes a gatsby-link component and an a tag:

import GatsbyLink from 'gatsby-link'
import PropTypes from 'prop-types'
import React from 'react'

export default function Link(props) {
  const { href, to, ...others } = props

  if (to) {
    return (
      <GatsbyLink {...others} to={to} />
    )
  }

  return (
    <a {...others} href={href} target="_blank" />
  )
}

Link.propTypes = {
  href: PropTypes.string,
  to: PropTypes.string,
}

All 17 comments

I think you need to use a Gatsby-Link

I want to create a link to outside of the router of gatsby. I think gatsby-link doesn't provide this function. I tried using Link tag but had no success. Could you explain how to use it in more detail?

I succeed with setting window.location to that url with this following code:

class Page extends React.Components {
  render() {
    function moveToAdmin() {
      if (typeof window !== 'undefined') {
        window.location = '/admin/';
      }
    }
    return (
      <a onClick={moveToAdmin} href="#">Link to admin page</a>
    );
  }
}

It is working as I wanted, but it has some lint errors. Is there any neat solution?

You should just be able to do <a href="/admin/">Link to admin page</a>

But yeah, gatsby-link doesn't know all possible routes since routes are lazy-loaded so it assumes the link will work.

We should actually, looking at the code, probably add support for detecting external links and treat those like normal <a> tags as well https://github.com/gatsbyjs/gatsby/blob/940563bc9519e74424a0905126cef0f768067fc7/packages/gatsby-link/src/index.js#L108

I've been doing a little Link component that composes a gatsby-link component and an a tag:

import GatsbyLink from 'gatsby-link'
import PropTypes from 'prop-types'
import React from 'react'

export default function Link(props) {
  const { href, to, ...others } = props

  if (to) {
    return (
      <GatsbyLink {...others} to={to} />
    )
  }

  return (
    <a {...others} href={href} target="_blank" />
  )
}

Link.propTypes = {
  href: PropTypes.string,
  to: PropTypes.string,
}

@dustinhorton your component did the trick, thanks! Just curious as I'm still getting the ropes of react/gatsby - but why is it necessary to make a "dumb" component like this and it is functional, but when I do regular anchor tag markup in /pages/index.js it is not functional?

@tetreault Great! Not totally sure鈥攊f you're linking to 'local/internal' pages within your app, it's because GatsbyLink has some specific functionality (like preventing full page loads, resource loading), and accomplishes that via different props (to for GatsbyLink vs href for an a).

An example similar to @dustinhorton's was added to the gatsby-link docs recently.

Closing this, please reopen if I've missed something.

@m-allanson just curious, is there any reason why the logic in the component specified above isn't just integrated into gatsby-link as opposed to wrapping gatsby-link in this way? Again - been learning more about react and its ecosystem (including Gatsby) so am just trying to understand these things better. Thanks!

There was some discussion about it, I'll see if I can dig it out - essentially it's very difficult to know which links are internal or external links.

Here we go: https://github.com/gatsbyjs/gatsby/issues/4662#issuecomment-375809110

thanks @m-allanson ! and you're right, I had a bit of tunnel vision since I was just focused on my use case but yeah you're right in regards to knowing how to handle the links

I wonder how do you fix it if you want to open in the same page? if you don't have target _blank it won't work.

@hackhat Mind clarifying what you're looking to do? target="_blank" would open the link in a new tab鈥攖he default functionality (no target prop) should open in the same tab.

@dustinhorton I want to open in the same page, but not to go through gatsby router because it will go to page not found. If I refresh the page it correctly loads the static html file.

@hackhat <a href="http://foo.com">Link</a> should do exactly that.

Thanks but for some reason is not doing that :(

here are my plugins if it helps, but I'm not doing any kind of magic:

[
  {
    resolve: `@wapps/gatsby-plugin-material-ui`,
    options: {},
  },
  `gatsby-transformer-sharp`,
  `gatsby-plugin-sharp`,
  {
    resolve: `gatsby-plugin-sitemap`,
    options: {
      exclude: [
        '/internal/**',
      ],
    },
  },
  `gatsby-plugin-catch-links`,
  `gatsby-plugin-emotion`,
  `gatsby-plugin-typescript`,
  'gatsby-plugin-react-helmet',
  'gatsby-plugin-offline',
  {
    resolve: `gatsby-source-filesystem`,
    options: {
      path: `${config.rootDir}/src/content/pages`,
      name: 'markdown-pages',
    },
  },
  {
    resolve: `gatsby-source-filesystem`,
    options: {
      path: `${config.rootDir}/src/content/images`,
      name: 'images',
    },
  },
  {
    resolve: `gatsby-transformer-remark`,
    options: {
      plugins: [
        {
          resolve: `gatsby-remark-images`,
          options: {
            // It's important to specify the maxWidth (in pixels) of
            // the content container as this plugin uses this as the
            // base for generating different widths of each image.
            maxWidth: 1200,
            linkImagesToOriginal: false,
            backgroundColor: 'transparent',
            withWebp: true,
          },
        },
        {
          resolve: 'gatsby-remark-component',
        },
      ],
    },
  },
]

I'm also experiencing the same issue as @hackhat. A plain a tag still does the push-state, which means I'm unable to link to my Netlify CMS page from my site. If I add the target="_blank" attribute, the link works as expected

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dustinhorton picture dustinhorton  路  3Comments

jimfilippou picture jimfilippou  路  3Comments

kalinchernev picture kalinchernev  路  3Comments

brandonmp picture brandonmp  路  3Comments

hobochild picture hobochild  路  3Comments