Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warning: Prop className did not match. #7423

Closed
SarKurd opened this issue May 25, 2019 · 35 comments
Closed

Warning: Prop className did not match. #7423

SarKurd opened this issue May 25, 2019 · 35 comments

Comments

@SarKurd
Copy link
Contributor

SarKurd commented May 25, 2019

I have been having this issue since last night, i did some research but couldn't find any solution

I'm not using Material ui or Styled components

CustomLink

import { withRouter } from "next/router";
import Link from "next/link";
import React, { Children } from "react";
import cx from "classnames";

const ActiveLink = ({ router, children, ...props }) => {
  const child = Children.only(children);

  const className = cx(child.props.className, {
    [props.activeClassName]: router.asPath === props.as && props.activeClassName
  });

  delete props.activeClassName;

  return <Link {...props}>{React.cloneElement(child, { className })}</Link>;
};

export default withRouter(ActiveLink);

Nav.js

import "../../static/styles/Nav.scss";

const Nav = () => {
  return (
    <nav className="navbar">
      <Link
        href="/player?name=xXSARKURDZz&platform=psn"
        as="/player/psn/xXSARKURDZz"
        activeClassName="navbar__item-active"
      >
        <a className="navbar__item">Profile</a>
      </Link>

      <Link
        href="/gambit?name=xXSARKURDZz&platform=psn"
        as="/player/psn/xXSARKURDZz/gambit"
        activeClassName="navbar__item-active"
      >
        <a className="navbar__item">Gambit</a>
      </Link>
    
    </nav>
  );
};

export default Nav;
@c0b41
Copy link
Contributor

c0b41 commented May 25, 2019

duplicate #7322

@timneutkens
Copy link
Member

duplicate of #7322

@timneutkens
Copy link
Member

Actually seems like you're doing something wrong, eg delete props.activeClassName; modifies the props, which you shouldn't do.

@SarKurd
Copy link
Contributor Author

SarKurd commented May 26, 2019

Thanks for the info. is there any solution for that at this moment?

@timneutkens
Copy link
Member

timneutkens commented May 26, 2019

In your case it doesn't seem like a problem in Next.js, but rather with your own code.

Please use the issue template in the future.

@dubKelly
Copy link

@Sergioamjr
Copy link

I fixed this issue editing my .babelrc file to

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "styled-components",
      { "ssr": true, "displayName": true, "preprocess": false }
    ]
  ]
}

@codyng
Copy link

codyng commented Oct 11, 2019

Thanks Sergioamjr!!
This solves the issue.

@ch3ll0v3k
Copy link

ch3ll0v3k commented Dec 8, 2019

Sergioamjr

.babelr

Dude you are the best. Thank you

@hutber
Copy link

hutber commented Dec 27, 2019

Why would this error occur when the OP isn't using style-components or MUI?

@5ervant
Copy link

5ervant commented Feb 28, 2020

I fixed this issue editing my .babelrc file to

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "styled-components",
      { "ssr": true, "displayName": true, "preprocess": false }
    ]
  ]
}

But installing babel-plugin-styled-components on a next-expo app with @expo/next-adapter takes forever.

@flppv
Copy link

flppv commented Mar 19, 2020

How to call a preset if I use a Typescript?

@gauravkrp
Copy link

Use nextjs dynamic import and pass ssr option to be false.
https://nextjs.org/docs/advanced-features/dynamic-import

I just discovered this method and it works in my case as my components has data to load on client side. option SSR needs to be false so that component is loaded on the client side dynamically and is not SSR.
In my case, the slider components has classes that are initialized and added to elements on client side after the document window is ready. So, the solution will work in all similar cases where the classes are initialized and added on the client side. See my code below.

const AGSlider = dynamic( () => import('../components/slider'), { ssr: false, loading: () => <Loader /> } )

@diegomjasso
Copy link

The solution is here: https://stackoverflow.com/a/61621949/7741752

@kevinseabourne
Copy link

kevinseabourne commented Jun 18, 2020

I literally made an exact copy of the styled components example on codesandox and it still did not work !!. I ended up creating a new create-next-app with the styled components example because it works !!! i don't know how... but it will do for now.

@zer0blockchain
Copy link

This fixed it for me
https://github.com/MarchWorks/nextjs-with-material-ui-and-styled-components/blob/master/.babelrc

@paulius1990
Copy link

@SarKurd Does this solution solved?
None From above worked for me. Still exists in dev environment.

@SarKurd
Copy link
Contributor Author

SarKurd commented Oct 14, 2020

@paulius1990 Everybody is throwing their answers here, i literally said i don't use Material UI or styled components and got flagged as duplicate so i gave up and i haven't used active class name for dynamic pages for a very long time as i didn't have a use case for it so i'm not sure if the issue is still there

have you tried the official example? https://github.com/vercel/next.js/tree/canary/examples/active-class-name

Currently i do this for NON-dynamic pages

import Link from 'next/link';
import { useRouter } from 'next/router';
import classNames from 'classnames';

const ActiveLink = ({ children, className = '', activeClassName, onClick, ...props }) => {
    const { pathname } = useRouter();

    return (
        <Link {...props}>
            <a
                className={classNames(className, {
                    [activeClassName]: pathname === props.href,
                })}
                onClick={onClick}
            >
                {children}
            </a>
        </Link>
    );
};

export default ActiveLink;
   <ActiveLink
                href="/"
                className="link"
                activeClassName="active"
            >
                Home
  </ActiveLink>

@paulius1990
Copy link

@SarKurd Thanks for your response, but in my case i don't use className approach we need to stick to styled components

@SarKurd
Copy link
Contributor Author

SarKurd commented Oct 14, 2020

have you tried the accepted answer, looks like it works for most

@paulius1990
Copy link

Yes, i tried all mentioned solutions and different babel configurations with no effort

@gajus
Copy link

gajus commented Oct 20, 2020

Ensure that you do not have two different version of webpack installed.

I had webpack@4.44.1 and webpack@4.44.2 in my dependency tree (npm ls --depth=2) and this was causing this issue.

This is because next.js has a hardcoded version of a specific webpack.

"webpack": "4.44.1",

This may also happen if you have upgraded to NPM v7. NPM v7 will attempt to resolve peerDependencies, which in my case was pulling in webpack v5 along with v4.

@hutber
Copy link

hutber commented Oct 20, 2020

Ye, I had wondered how NPM v7 and its peerDependencies would effect all of my projects!! Brilliant!

@gajus
Copy link

gajus commented Oct 20, 2020

Yeah, I don't recommend upgrading to v7 until they add overrides. I found it virtually impossible to make it work. You can of course disable the peer installing behaviour, but then why update at all.

@paulius1990
Copy link

paulius1990 commented Oct 21, 2020

Ensure that you do not have two different version of webpack installed.

I had webpack@4.44.1 and webpack@4.44.2 in my dependency tree (npm ls --depth=2) and this was causing this issue.

This is because next.js has a hardcoded version of a specific webpack.

"webpack": "4.44.1",

This may also happen if you have upgraded to NPM v7. NPM v7 will attempt to resolve peerDependencies, which in my case was pulling in webpack v5 along with v4.

I don't have webpack on my Next.JS app, here my pacakge.json

"dependencies": {
    "@chakra-ui/core": "^0.8.0",
    "@emotion/core": "^10.0.35",
    "@emotion/styled": "^10.0.27",
    "@types/react-slick": "^0.23.4",
    "emotion-theming": "^10.0.27",
    "lodash": "^4.17.20",
    "next": "9.5.5",
    "react": "16.14.0",
    "react-dom": "16.14.0",
    "react-hook-form": "^6.9.2",
    "react-is": "16.13.1",
    "react-slick": "^0.27.12",
    "slick-carousel": "^1.8.1",
    "styled-components": "5.2.0",
  },
  "devDependencies": {
    "@babel/core": "7.12.3",
    "@babel/preset-env": "7.12.1",
    "@babel/preset-react": "7.12.1",
    "@babel/preset-typescript": "7.12.1",
    "@nrwl/cli": "10.3.1",
    "@nrwl/cypress": "10.3.1",
    "@nrwl/eslint-plugin-nx": "10.3.1",
    "@nrwl/jest": "10.3.1",
    "@nrwl/next": "10.3.1",
    "@nrwl/react": "10.3.1",
    "@nrwl/web": "10.3.1",
    "@nrwl/workspace": "10.3.1",
    "@testing-library/react": "11.1.0",
    "@types/jest": "26.0.14",
    "@types/lodash": "^4.14.162",
    "@types/node": "~14.11.10",
    "@types/react": "16.9.53",
    "@types/react-dom": "16.9.8",
    "@types/react-is": "16.7.1",
    "@types/styled-components": "5.1.4",
    "@typescript-eslint/eslint-plugin": "4.4.1",
    "@typescript-eslint/parser": "4.4.1",
    "babel-jest": "26.5.2",
    "babel-plugin-styled-components": "1.11.1",
    "cypress": "^5.4.0",
    "dotenv": "8.2.0",
    "eslint": "7.11.0",
    "eslint-config-prettier": "6.13.0",
    "eslint-plugin-cypress": "^2.11.2",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsx-a11y": "6.3.1",
    "eslint-plugin-react": "7.21.4",
    "eslint-plugin-react-hooks": "4.1.2",
    "jest": "26.5.3",
    "prettier": "2.1.2",
    "ts-jest": "26.4.1",
    "ts-node": "~9.0.0",
    "typescript": "~4.0.3"
  }

@gajus
Copy link

gajus commented Oct 21, 2020

Just because you don't have it in package.json, doesn't mean it doesn't get installed. Use npm ls --depth=2 to inspect your dependency tree.

@sorenabedi
Copy link

sorenabedi commented Oct 30, 2020

hi everyone,
I had the same problem with materialUI and FluentUI front-end frameworks
my Dependencies :

"dependencies": {
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"axios": "^0.21.0",
"jss-rtl": "^0.3.0",
"next": "10.0.0",
"next-pwa": "^3.1.5",
"next-redux-wrapper": "^6.0.2",
"next-seo": "^4.14.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",
"sass": "^1.27.0"
},
"devDependencies": {
"@types/redux-persist": "^4.3.1",
"redux-devtools-extension": "^2.13.8",
"typescript": "^4.0.5"
}

my workaround

1- downgrade these four:

"next": "^9.5.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"sass": "^1.26.11"

2- remove .next and node_modules folders

3- reinstall yarn install

I hope it helps

@dkodeit
Copy link

dkodeit commented Oct 31, 2020

Ran into this same issue amd in my case I found that when using asPath it triggers the className doesn't match issue. If I use router.route or router.pathname everything works without issue. Note the OP's code is using asPath as well.

NO GOOD

<style jsx>{`
  .sidebar {
    ${router.asPath === '/some-route'
      ? 'border: 2px solid red;'
      : 'border: 2px solid blue;'}
  }
`}</style>

GOOD

<style jsx>{`
  .sidebar {
    ${router.route === '/some-route'
      ? 'border: 2px solid red;'
      : 'border: 2px solid blue;'}
  }
`}</style>

@paulius1990
Copy link

Just because you don't have it in package.json, doesn't mean it doesn't get installed. Use npm ls --depth=2 to inspect your dependency tree.

Having only one webpack 4.44.1 version, also npm version 6.14.4 . So still not the solution in my case

@paulius1990
Copy link

Ran into this same issue amd in my case I found that when using asPath it triggers the className doesn't match issue. If I use router.route or router.pathname everything works without issue. Note the OP's code is using asPath as well.

NO GOOD

<style jsx>{`
  .sidebar {
    ${router.asPath === '/some-route'
      ? 'border: 2px solid red;'
      : 'border: 2px solid blue;'}
  }
`}</style>

GOOD

<style jsx>{`
  .sidebar {
    ${router.route === '/some-route'
      ? 'border: 2px solid red;'
      : 'border: 2px solid blue;'}
  }
`}</style>

doesn't work for me :(

@paulius1990
Copy link

hi everyone,
I had the same problem with materialUI and FluentUI front-end frameworks
my Dependencies :

"dependencies": {
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"axios": "^0.21.0",
"jss-rtl": "^0.3.0",
"next": "10.0.0",
"next-pwa": "^3.1.5",
"next-redux-wrapper": "^6.0.2",
"next-seo": "^4.14.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",
"sass": "^1.27.0"
},
"devDependencies": {
"@types/redux-persist": "^4.3.1",
"redux-devtools-extension": "^2.13.8",
"typescript": "^4.0.5"
}

my workaround

1- downgrade these four:

"next": "^9.5.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"sass": "^1.26.11"

2- remove .next and node_modules folders

3- reinstall yarn install

I hope it helps

Tried dowgraded React & Next versions even updated to the latest React 17 and Next 10 versions, nothing worked for me.

@oliver021
Copy link

I fixed this issue editing my .babelrc file to

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "styled-components",
      { "ssr": true, "displayName": true, "preprocess": false }
    ]
  ]
}

it's working!!!

@marcvangend
Copy link
Contributor

@dkodeit wrote:

Ran into this same issue amd in my case I found that when using asPath it triggers the className doesn't match issue. If I use router.route or router.pathname everything works without issue. Note the OP's code is using asPath as well.

That sounds a lot like what I'm seeing. Not using styled components or MUI. Today I added router.asPath to set an 'active' class on menu items and the error appeared.
It only seems to happen when the menu items are rendered client side; pre-rendered pages do not trigger the error as far as I can see. Unfortunately, changing router.asPath to router.pathname is not an option when you're using dynamic routes like [...slug].js.

@marcvangend
Copy link
Contributor

I found a solution for my situation (as said: not using styled components or Material UI, just like @SarKurd and @dkodeit) once I realised what the warning really means.

If I understand correctly, Next.js expects a component to generate identical output on the client side and the server side. However, useRouter.asPath() does not work on the server side (issue: #8757) and so the thing that depends on the asPath value will not match.

My solution is to treat the values I'm modifying as state using the useState hook, and implement the useEffect hook to set the state based on the router's asPath value.

To illustrate, first my code looked something like this (simplified version):

import Link from "next/link";
import { useRouter } from "next/router";

function MainMenu({ menuItems }) {
  const currentPath = useRouter().asPath;

  return (
    <nav>
      <ul className="menu">
        {menuItems.map((menuItem) => {
          const classNames = ["menu-item"];
          menuItem.attributes.url === currentPath && classNames.push("active");
          return (
            <li key={menuItem.id} className={classNames.join(" ")}>
              <Link href={menuItem.attributes.url}>
                <a>{menuItem.attributes.title}</a>
              </Link>
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

export default MainMenu;

And now it changed to this:

import Link from "next/link";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";

function MainMenu({ menuItems }) {
  // Initialize the state as a copy of the menuItems prop.
  const [classedMenuItems, setClassedMenuItems] = useState(menuItems);
  const currentPath = useRouter().asPath;

  // Apply the "active" class as a side-effect dependent on currentPath.
  useEffect(() => {
    const processedMenuItems = menuItems.map((menuItem) => {
      const classNames = ["menu-item"];
      menuItem.attributes.url === currentPath && classNames.push("active");
      menuItem.className = classNames.join(" ");
      return menuItem;
    });
    setClassedMenuItems(processedMenuItems);
  }, [menuItems, currentPath]);

  return (
    <nav>
      <ul className="menu">
        {classedMenuItems.map((menuItem) => {
          return (
            <li key={menuItem.id} className={menuItem.className}>
              <Link href={menuItem.attributes.url}>
                <a>{menuItem.attributes.title}</a>
              </Link>
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

export default MainMenu;

So that's how I got rid of the warning.

Maybe @timneutkens can confirm that my initial code was the type of problem he meant when he wrote "you're doing something wrong, eg delete props.activeClassName; modifies the props, which you shouldn't do" and let us know if this is the correct solution.

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests