React Responsive Components SSR #3527
Replies: 4 comments 2 replies
-
Have you tried it? I don't see anything wrong with the approach. |
Beta Was this translation helpful? Give feedback.
-
That should work, and you can probably avoid an custom context and use the useMatches hook to access the data of the root route like this function useDevice() {
let [rootMatch] = useMatches()
return rootMatch.data?.isMobileOnly ?? false // fallback to false in case it's not defined
} The only concern with this would be what happens if the user makes the browser small, so the user should get the mobile component but it got the desktop because of the user-agent. And in the other direction, a large iPad should receive a mobile or desktop component? The screen size is large enough to use the desktop, but the user-agent is probably gonna match as mobile. I think, the safest way to do this, is to use CSS and not JS, use actual CSS media queries to hide/show or change how a component looks like, you can even use CSS to detect if the user pointer is a cursor or if it's touch to change the size of the elements to make it easier to use on touch devices, like iPad which should match a screen size of desktop but it's still touch and needs larger buttons. |
Beta Was this translation helpful? Give feedback.
-
@niklasgrewe I know this discussion is a bit old now, but did you ever find a nice solution for this? I too have a project where I cannot just use CSS and media queries, because on mobile I render completely different components that behave differently, the mobile components are not just a responsive version of the desktop components, they are completely different implementations that are more suitable to mobile device interactions. |
Beta Was this translation helpful? Give feedback.
-
I wanted to pre-render a page conditionally based on the device type on React/NextJS/SSR. I was able to do it by storing the user-agent in a context and reading it from a hook We create a context to store the parsed user-agent header. // userAgentContext.ts
import { userAgent } from "next/server";
import { createContext } from "react";
export type UserAgent = ReturnType<typeof userAgent>;
export const UserAgentContext = createContext<UserAgent | undefined>(undefined); We create a hook to consume the context and check device type. // useIsMobile.ts
import { useContext } from "react";
import { UserAgentContext } from "./userAgentContext.ts";
export const useIsMobile = () => {
const userAgent = useContext(UserAgentContext);
if (!userAgent) {
throw new Error("useIsMobile must be used within a UserAgentContext.Provider");
}
return userAgent.device.type === "mobile";
}; We can use a sever component as the layout (app router) to get the user agent from request headers // layout.tsx
"use server";
import { headers } from "next/headers";
import { userAgent } from "next/server";
import { LayoutClient } from "./layoutClient.ts";
export default async function Layout({ children }: { children: React.ReactNode }) {
const reqUserAgent = userAgent({ headers: headers() });
return <LayoutClient reqUserAgent={reqUserAgent}>{children}</LayoutClient>
} We can then pass the user agent to a client component that will provide the initial value for the context. Since client components with // layoutClient.tsx
"use client";
import { UserAgentContext } from "./userAgentContext.ts";
export default function LayoutClient({ reqUserAgent, children }: { reqUserAgent: UserAgent, children: React.ReactNode }) {
return <UserAgentContext.Provider value={reqUserAgent}>{children}</UserAgentContext.Provider>;
} Now when this page is rendered for the first time on the server with initial values, useIsMobile() should accurately return a value based on the user-agent device type. // page.tsx
"use client";
export default function Page() {
const isMobile = useIsMobile();
return isMobile ? <>Mobile</> : <>Desktop</>;
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi, i am looking for a solution to build components conditionally on server, based on the user agent. I have already seen many React packages like
react-responsive
or@react-hook/media-query
but they mostly only work client-side. Is there a way to conditionally build react components on server using remix?it seems that the popular
react-device-detect
package now supports ssr. Some developers use this in nextjs like this:How can i build something like this in remix? Can i maybe use the root loader to achieve the same like this:
and then inside my pages:
Would this be a good approach or do you have even better ideas?
Beta Was this translation helpful? Give feedback.
All reactions