Errors I dealt with in Next.js - styled components, pages, types

Dahye Ji - Dec 23 '21 - - Dev Community

1. Warning : Props 'className' did not match Server: ' ' Client: ' '

I wanted to add styled components so I installed styled-components

yarn add styled-components
Enter fullscreen mode Exit fullscreen mode

and added this code below in package.json

  "resolutions": {
    "styled-components": "^5"
  }
Enter fullscreen mode Exit fullscreen mode

(The code above was recommended if you use a package manager like yarn that supports the "resolutions" package.json field)
and then I imported styled-components and used it.

import styled from "styled-components";

export const StyledLink = styled.a`
  border: none;
  padding: 0.8rem 1.4rem;
  margin: 1rem;
  cursor: pointer;
  background-color: #2b2b2b;
  color: white;
  border-radius: 2rem;
  font-weight: 600;
  &:hover {
    background-color: #fc4961;
  }
`
Enter fullscreen mode Exit fullscreen mode

like these and but then I got an error saying Warning : Props 'className' did not match Server: ' ' Client: ' ' what it means is it literally doesn't match the className in Server side and in Client side. So, Next.js does SSR first and then CSR partially. The class name doesn't match when it renders and that's why it happened. So to solve this problem, I installed babel-plugin-styled-components

yarn add --dev @types/styled-components babel-plugin-styled-components
Enter fullscreen mode Exit fullscreen mode

and added babelrc in the root of project directory. Then added this code below

{
    "presets": [
        "next/babel"
    ],
    "plugins": [
        [
            "babel-plugin-styled-components",
            {
                "fileName": true,
                "displayName": true,
                "pure": true
            }
        ]
    ]
}

Enter fullscreen mode Exit fullscreen mode

But then I found that I can import { ServerStyleSheet } from 'styled-components';
I think I might have to redo it.
Links I read:
https://stackoverflow.com/questions/51791163/warning-prop-classname-did-not-match-when-using-styled-components-with-seman
https://sumini.dev/guide/004-nextjs-typescript-styled-components/
https://velog.io/@hwang-eunji/Styled-components-nextjs%EC%97%90%EC%84%9C-className-%EC%98%A4%EB%A5%98

Then I got another Error... It was okay when I checked my code through live server but when I deployed them, It kept failing.

2. Build optimization failed: found page without a React Component as default export in pages/styledComponent/styles

But I didn't carefully read those error massages. Only read those lines marked in red and was wondering why it kept failed.
error-msg
I read the messages line by line then found these Build optimization failed: found page without a React Component as default export in
pages/styledComponent/styles

Link that helped my problem: https://stackoverflow.com/questions/65598753/cant-build-react-next-project-found-page-without-a-react-component-as-default/65598867
You should move your components outside the pages folder. pages/ should only be used for page components as Next.js routing is based on its structure.
My styled-components file was within pages directory... which it shouldn't have been. So I moved it to other directory and it worked fine.

3. Error: Do not use the HTML <a> tag to navigate to /beers/ale/. Use Link from 'next/link' instead.

error3
I used <a> tags to link pages and had this problem. So I checked Next.js documentation and added Links like this way

import { NextPage } from "next";
import Link from "next/link";

const BeerPage: NextPage = () => {
    return (
        <div>
            <h1>Beers Page</h1>
            <p>
                <Link href="beers/ale">
                    <a>Ale</a>
                </Link>
            </p>
            <p>
                <Link href="beers/stouts">
                    <a>Stouts</a>
                </Link>
            </p>
            <p>
                <Link href="beers/red-ale">
                    <a>Red Ale</a>
                </Link>
            </p>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

4. Warning: passHref is missing.

Then I had these messages when I deployed.
msgs
I didn't like the long code repeating and also didn't like the messages so I looked up documentation again... so I wanted to add passHref so that I can get rid of those messages.
https://nextjs.org/docs/messages/link-passhref

import Link from "next/link";
import { StyledLink } from "./styles";
import styled from "styled-components";

const NavLink = ({ href, name }) => {
    return (
        <Link href={href} passHref>
            <StyledLink>{name}</StyledLink>
        </Link>
    )
}

export default NavLink;
Enter fullscreen mode Exit fullscreen mode

Then I had red lines on href and name and that was because they didn't have types.
So, I added types and imported in NavLink

export interface Links {
    href: string,
    name: string,
}
Enter fullscreen mode Exit fullscreen mode

I solved problems I had but I wanted to make code simpler and using NavLink, depending on links I wanted to change styling as well. So This is how refactored my code.

NavLink.tsx

import Link from "next/link";
import { StyledLink } from "./styles";
import styled from "styled-components";
import { Links } from "../types/Links";

const StyledLink2 = styled(StyledLink)`
    &:hover {
        background-color: #2b8aff;
    }
`

const NavLink = ({ href, name, bgColor }: Links) => {
    if (bgColor === "blue") {
        return (
            <Link href={href} passHref>
                <StyledLink2>{name}</StyledLink2>
            </Link>
        )
    }
    return (
        <Link href={href} passHref>
            <StyledLink>{name}</StyledLink>
        </Link>
    )
}

export default NavLink;
Enter fullscreen mode Exit fullscreen mode

I wanted to give null value to bgColor for some Links so I added type null in Links

export interface Links {
    href: string,
    name: string,
    bgColor: string | null
}
Enter fullscreen mode Exit fullscreen mode

index.tsx (Beers page directory)

import { Menu, Container } from "../../components/styles";
import NavLink from "../../components/NavLink";

const BeerPage: NextPage = () => {
    return (
        <div>
            <Menu>Beers🍺</Menu>
            <Container>
                <NavLink href={"/beers/ale"} name={"Ale"} bgColor="blue" />
                <NavLink href={"/beers/stouts"} name={"Stouts"} bgColor="blue" />
                <NavLink href={"/beers/red-ale"} name={"Red Ale"} bgColor="blue" />
            </Container>
        </div >
    )
}

export default BeerPage;
Enter fullscreen mode Exit fullscreen mode

index.tsx (Wine page directory)

import type { NextPage } from "next";
import { Menu, Container } from "../../components/styles";
import NavLink from "../../components/NavLink";


const WinePage: NextPage = () => {
  return (
    <div>
      <Menu>Wines🍷</Menu>
      <Container>
        <NavLink href={"/wines/port"} name={"Port"} bgColor={null} />
        <NavLink href={"/wines/reds"} name={"Reds"} bgColor={null} />
        <NavLink href={"/wines/rose"} name={"Rose"} bgColor={null} />
        <NavLink href={"/wines/sparkling"} name={"Sparkling"} bgColor={null} />
        <NavLink href={"/wines/whites"} name={"White"} bgColor={null} />
        <NavLink href={"/wines/dessert"} name={"Dessert"} bgColor={null} />
      </Container>
    </div >
  )
}

export default WinePage;
Enter fullscreen mode Exit fullscreen mode

I did bgColor="" first and it worked without error but it didn't feel right.. so I changed it to {null} after reading some stuffs on stackoverflow. It said to give either null or undefined value if I wanted to pass empty props.

These are how they look like now.
Wines
Beer

*I might be wrong for some stuff since I am totally new to Typescript and Next.js. Alslo the code will be refactored as well.
Feel free to let me know if you find errors or things that I shouldn't do!

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