className did not match between server and client when using useBreakpointValue
See original GitHub issueBug report
Describe the bug
Using useBreakpointValue in SSR NextJS project I am receiving in the console:
Warning: Prop `className` did not match. Server: "chakra-heading css-1jlcwm0" Client: "chakra-heading css-2bykvb"
So the issue is I guess, that the Server delivers some style, e.g. for base
breakpoint which is different from the actual style on the client, e.g. when it’s a desktop (lg breakpoint) device.
I guess the server would somehow need to deliver the right styles for a device breakpoint. Not sure how that would work, there are some ways to figure out which browser a client uses (e.g. mobile android chrome, etc.) and then assume if its a base, sm, md, lg, xl device.
I am not even sure if thats a bug at all or if that is simply a thing that cannot be fixed due to the nature of server side rendering.
To reproduce
See this example, or check the console in https://codesandbox.io/s/modest-haze-pn9z2?file=/pages/index.js
import { Heading, HeadingProps, useBreakpointValue } from "@chakra-ui/react";
interface DefaultHeadlineProps extends HeadingProps {
size: "xs" | "s" | "m" | "l";
}
export const DefaultHeadline: React.FC<DefaultHeadlineProps> = ({
as,
size,
children,
...props
}) => {
const headingSizes = {
xs: { base: "sm", md: "md", lg: "lg", xl: "xl" },
s: { base: "md", md: "lg", lg: "xl", xl: "2xl" },
m: { base: "lg", md: "xl", lg: "2xl", xl: "3xl" },
l: { base: "xl", md: "2xl", lg: "3xl", xl: "4xl" },
};
const headingSize = useBreakpointValue(headingSizes[size]);
const headingMarginBottom = {
xs: { base: "2", md: "4", lg: "6" },
s: { base: "4", md: "6", lg: "10" },
m: { base: "5", md: "7", lg: "12" },
l: { base: "6", md: "8", lg: "12" },
};
const marginBottomSize = useBreakpointValue(headingMarginBottom[size]);
return (
<Heading
as={as}
fontFamily="Source Sans Pro"
size={headingSize}
textTransform="uppercase"
fontWeight="bold"
marginBottom={marginBottomSize}
{...props}
>
{children}
</Heading>
);
};
Minimal reproduction
https://codesandbox.io/s/modest-haze-pn9z2?file=/pages/index.js
Expected behavior
Generate the same css on server and client.
Additional context
I guess the issue is somewhere here: https://github.com/chakra-ui/chakra-ui/blob/develop/packages/media-query/src/use-breakpoint.ts
The problem is, that we are dependant on the window object which is simply not there on SSR. Is there any way to handle that case for SSR rendered apps?
As a workaround I could just use create different components for my heading sizes like that, which seems to work. Could some1 explain to me why this works? I don’t know if I have the right piece of code here: https://github.com/chakra-ui/chakra-ui/blob/develop/packages/layout/src/heading.tsx
export const HeadlineL: React.FC<HeadingProps> = ({
as,
children,
...props
}) => {
return (
<Heading
as={as}
fontSize={{ base: "xl", md: "2xl", lg: "3xl", xl: "4xl" }}
textTransform="uppercase"
fontWeight="bold"
marginBottom={{ base: "6", md: "8", lg: "12" }}
{...props}
>
{children}
</Heading>
);
};
Edit: I just noticed, that for that specific case I could also solve the responsive font sizes via theme:
const extendedTheme = {
components: {
Heading: {
sizes: {
"6xl": {
fontSize: { base: "10px", lg: "50px" },
},
},
},
},
};
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:16 (5 by maintainers)
Top GitHub Comments
Here’s a workaround for now (in Typescript, just remove the types if you’re in js):
file: hooks/useBreakpointValue/index.tsx
Hey, I think this needs to be reopened as of @chakra-ui/media-query@1.2.3