Live example available here
I’m trying to make a basic layout where, on mobiles, only the latest posts appear. On desktop, the left column should be the posts and the right column the top categories and most popular posts.
Here is the layout:
const IndexLayout: React.FC<IndexLayoutProps> = ({}) => { const cols = useScreenType() return cols === '2-cols' ? ( <div className="w-full flex justify-between items-start"> <ListPosts data-comp="ListPosts" className="w-4/6" /> <div className="sticky ml-12 w-2/6 flex flex-col"> <TopCategories data-comp="TopCategories" className="w-full" /> <PopularPosts data-comp="PopularPosts" className="mt-4" /> </div> </div> ) : ( <ListPosts data-comp="ListPosts" className="w-full" /> ) }
Here’s the useScreenType
hook:
import { useMediaQuery } from 'react-responsive' export const useScreenType = () => { const is2Cols = useMediaQuery({ minWidth: 1300 }) const is1Cols = useMediaQuery({ minWidth: 800 }) if (is2Cols) { return '2-cols' } if (is1Cols) { return '1-cols' } return 'fullscreen' }
And I keep getting this error:
Warning: Expected server HTML to contain a matching <div> in <div>. div ListPosts@webpack-internal:///./components/posts/ListPosts.tsx:31:19 div IndexLayout@webpack-internal:///./components/layout/IndexLayout.tsx:28:149 div Index@webpack-internal:///./pages/index.tsx:24:149 ApolloProvider@webpack-internal:///./node_modules/@apollo/client/react/context/ApolloProvider.js:13:18 s@webpack-internal:///./node_modules/next-apollo/dist/index.es.js:26:1911 div div MyApp@webpack-internal:///./pages/_app.tsx:37:19 ErrorBoundary@webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ErrorBoundary.js:23:47 ReactDevOverlay@webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ReactDevOverlay.js:73:20 Container@webpack-internal:///./node_modules/next/dist/client/index.js:155:20 AppContainer@webpack-internal:///./node_modules/next/dist/client/index.js:643:18 Root@webpack-internal:///./node_modules/next/dist/client/index.js:779:19
Now I think the issue is due to the useScreenType
hook not being able to get a width because window
isn’t defined on the server. But how can I fix this issue? And not only do I get an error, but my HTML renders weirdly.
The final render ends up being something like this (when it renders as ‘2-cols’):
<div class="flex flex-col justify-start items-start w-full"> <div class="mt-6 w-full"></div> <div class="mt-4 flex items-center cursor-pointer transform transition hover:scale-105 text-sm"> <div class="w-full p-6 rounded-lg flex flex-col dark:bg-gray-800 shadow-md"></div> <div class="mt-4 p-6 rounded-lg flex flex-col dark:bg-gray-800 shadow-md"></div> </div> </div>
Note: I am using Next.js v10.2.0
Code can be found on GitHub
Advertisement
Answer
For anyone wondering how I fixed this, I ditched the responsive design with logic and switched to CSS. Here is my layout post fix (changed some classes with the lg
prefix [documentation]):
const IndexLayout: React.FC<IndexLayoutProps> = ({}) => { return ( <div className="mt-12 lg:mt-24 w-5/6 mx-auto flex items-start"> <div className="w-full flex justify-between items-start"> <ListPosts className="lg:w-4/6 w-full" /> <div className="hidden sticky ml-12 w-2/6 lg:flex flex-col"> <TopCategories className="w-full" /> <PopularPosts className="mt-4" /> </div> </div> </div> ) }