gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.27k stars 10.32k forks source link

Link's activeClassName not working on page load #10586

Closed sylvhama closed 5 years ago

sylvhama commented 5 years ago

Description

This issue is similar to https://github.com/gatsbyjs/gatsby/issues/7502 and https://github.com/gatsbyjs/gatsby/issues/3238. The class is not added when loading the page but it works after user navigates via a link.

Steps to reproduce

You can look at Nav in https://github.com/sylvhama/shamann-gatsby It works in dev mode only for /, others pages don't seem active if you press F5. Build never works, what ever the page. Prod link: https://shamann.netlify.com/ However you will see the actice Link if user clicks on one of them.

Expected result

The Nav's link should have active class.

Actual result

The class active is missing.

arnriu commented 5 years ago

Path needs to be exact, gatsby-link uses isCurrent from reach-router Link to determine if link has active class or active style, and isCurrent require exact path. Logging routerElement from /gatsby/cache-dir/static-entry.js, that makes use of ServerLocation from reach-router to set router location in ssr, I see that url prop for each page has a trailing slash. E.g:

{ '$$typeof': Symbol(react.element),
  type: [Function: ServerLocation],
  key: null,
  ref: null,
  props:
   { url: '/showcase/',
     children:

............

Now from your Nav component, in <StyledLink to={link.path} activeClassName="active"> , your link.path has no trailing slash. It means taht it's not exactly equal to ServerLocation url prop on ssr. Your pages are generated without active class on links.

On first navigation, your page comes from your server, the ssr version. We just saw that it lacks active class on links, and why. Then your react comes to life and handle subsequent navigation and dom repaint. When react is active, your path location in reach router comes from your browser, and has no trailing slash since you didnt add them in your internal links. That's why it works on local dev mode (no ssr) or when you come from an internal link.

You could try adding trailing slash here <StyledLink to={`${link.path}/`} activeClassName="active"> to fix your problem, and maybe it could be fixed in gatsby later.

sylvhama commented 5 years ago

Thanks for your answer, I've applied your changes and it was still not working :/ But I noticed that removing the plugin gatsby-plugin-offline would fix everything oO

arnriu commented 5 years ago

Well, I cloned your repo, did npm i, changed Nav.js as explained in previous post, ran npm run build then npx http-server ./public, then tryid multiple refresh on multiple pages in chrome. Everything looks fine.

arnriu commented 5 years ago

Btw, offline plugin could still cause problems with cache. Be sure to clean your browser site data,

sylvhama commented 5 years ago

Yup I must have been biaised by my service worker, closing the issue. Thanks!

arnriu commented 5 years ago

You're welcome. If you do not want those trailing slash, you could try gatsby-plugin-remove-trailing-slashes . Let me know if it works for your case :)

sylvhama commented 5 years ago

@arnriu Sorry I am re-opening this because I've found something new:

My problem is: my activeClassName does not seem to work every times. Important detail: My navigation bar is rendered via wrapPageElement in gatsby-browser and gatsby-ssr because I don't want it to be unmounted at each route change because it has CSS transitions.

I don't think it's a trailing slash issue. I have console logged location.pathname. My build logs look like that:

7:39:03 PM: success onPostBootstrap — 0.299 s
7:39:12 PM: success Building production JavaScript and CSS bundles — 9.339 s
7:39:13 PM: /offline-plugin-app-shell-fallback/
7:39:13 PM: /404/
7:39:13 PM: /
7:39:13 PM: /relevant-experience/
7:39:13 PM: /showcase/
7:39:13 PM: /talks-open-source/
7:39:13 PM: /404.html
7:39:13 PM: success Building static HTML for pages — 0.965 s — 7/7 19.57 pages/second
7:39:14 PM: Generated public/sw.js, which will precache 9 files, totaling 290774 bytes.
7:39:14 PM: info Done building in 16.141 sec

Notice the offline-plugin-app-shell-fallback/. I also display location.pathname in my JSX. If you open dev tools and refresh, you will notice it for a very short time:

sylvhama commented 5 years ago

Work around: I've update the live version, I don't display my Nav bar if the path is offline-plugin-app-shell-fallback. That's a bit dirty and you can see the content jumping because the Nav will pop :/

gatsbot[bot] commented 5 years ago

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 💪💜

gatsbot[bot] commented 5 years ago

Hey again!

It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.

Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

Thanks again for being part of the Gatsby community!

amcsi commented 5 years ago

I'm getting this issue too with gatsby-plugin-offline. I don't wish to use gatsby-plugin-remove-trailing-slashes, because that involves creating redirects, and I don't want to increase the amount of round trips.

Has anyone been able to come up with a solution?

amcsi commented 5 years ago

In the end I've opted for @universse's solution here to not render any nav items in offline mode: https://github.com/gatsbyjs/gatsby/issues/11738#issuecomment-488660043

I believe this is the best solution, because:

MrRobotjs commented 3 years ago

I forgot when I received this solution but I’ve used it since GatsbyjsV2 and it has worked all the way through V3.


      resolve: 'gatsby-plugin-offline',
      options: {
        workboxConfig: {
            runtimeCaching: [
                {
                    urlPattern: /(\.js$|\.css$|static\/)/,
                    handler: `CacheFirst`,
                },
                {
                    urlPattern: /^https?:.*\/page-data\/.*\/(page-data|app-data)\.json$/,
                    handler: `NetworkFirst`,
                    options: {
                        networkTimeoutSeconds: 1,
                    },
                },
                {
                    urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
                    handler: `StaleWhileRevalidate`,
                },
                {
                    urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
                    handler: `StaleWhileRevalidate`,
                },
                {
                    urlPattern: /\/$/,
                    handler: `NetworkFirst`,
                    options: {
                        networkTimeoutSeconds: 1,
                    },
                },
            ],
        },
      },
    },