yocontra / react-responsive

CSS media queries in react - for responsive design, and more.
https://contra.io/react-responsive
MIT License
6.95k stars 297 forks source link

Server components #309

Closed SzymonGalazka closed 1 year ago

SzymonGalazka commented 1 year ago

Hi all, as React team has created the concept of Server Components, current react-responsive approach to rendering on the server is no longer working. Before the introduction of Server Components, you could use the Provider to supply react-responsive hooks with width prop on the server. I personally calculated the width based on User Agent data but it could've been placeholder value as well:

<ResponsiveContext.Provider
/// can be `value={{ width: 1440 }}` as well
            value={{ width: getUserAgentWidth(UAParser, userAgent) }}
          >
        <Page {...data} />
</ResponsiveContext.Provider>

with Server Components, Provider cannot be used on the server at all:

info  - Collecting page data ...TypeError: (0 , react_1.createContext) is not a function
    at ./src/Context.ts (..../.next/server/chunks/690.js:5314:57)
    at __nested_webpack_require_88007__ (.....next/server/chunks/690.js:5646:52)
    at ./src/useMediaQuery.ts (..../.next/server/chunks/690.js:5508:49)

You can test that behaviour in Next 13 which allows the use of Server Components.

You can bypass this by creating a client-side wrapper as described here but this only shifts the initialization of library to the client. You lose the benefit of having react-responsive on the server. Besides that, all components that use react-responsive in any way need to be client components too.

It will be nice to have the option to still use react-responsive and components that use it, on the server. Maybe using import { createServerContext } from 'react'?

panzacoder commented 1 year ago

I haven't gotten far in implementing an app with RSC, but I believe in this construct, react-responsive would fit best into a "use client" component.

One of the things about RSC is that they don't really have a finalized conceptual model for doing pre-rendering / static generation.

I'm not sure if there is a way in Next 13 to provide context to client-only components. In Gatsby there is a wrapRootElement API in gatsby-browser.js that would work well for this concept.

yocontra commented 1 year ago

It looks like you are using next.js - you can use use client or you can do:

import dynamic from "next/dynamic"
const MediaQuery = dynamic(() => import("react-responsive"), {
  ssr: false
})

Added this to the docs, closing.