react-native-magnus icon indicating copy to clipboard operation
react-native-magnus copied to clipboard

[Feature] Responsive Props

Open jsartisan opened this issue 3 years ago • 11 comments

Since magnus works on web too, adding responsive props to handle media query both on web and mobile devices is must-have feature.

jsartisan avatar Dec 23 '20 06:12 jsartisan

How would the High Level API be? Like Chakra UI's array syntax or something else?

kuasha420 avatar Jan 09 '21 11:01 kuasha420

We are trying to make the API similar to Chakra-UI.

jsartisan avatar Jan 11 '21 09:01 jsartisan

any progress on this? dripsy have something similar https://github.com/nandorojo/dripsy

ciocan avatar Feb 10 '21 09:02 ciocan

@ciocan We won't following dripsy approach because that is very inefficient because of https://www.npmjs.com/package/@artsy/fresnel

We are thinking to move with https://www.npmjs.com/package/react-native-media-query.

jsartisan avatar Feb 10 '21 10:02 jsartisan

How will you handle potentially duplicated side-effects then?

There's a performance hit you take for [server-side] rendering components your user isn't seeing, but even worse is the potential for duplicate side-effects [client-side].

Imagine a component that, when rendered [client-side?], emits a call to an analytics service. If this component exists in both a mobile and desktop branch, you're now double-stuffing your analytics. Hopefully your analytics service is smart enough to count only one call, but it's still a bad idea to duplicate components that have side-effects.

@artsy/fresnel will only client-render the breakpoint that matches your browser dimensions, so you don't have to worry about duplicate side-effects.

https://artsy.github.io/blog/2019/05/24/server-rendering-responsively/#Rely.solely.on.CSS

It doesn't seem that inefficient to render all breakpoints, actually, since it is only done as a fallback in the off-chance a mobile user agent isn't detected properly:

But with @artsy/fresnel as our primary approach, we felt that we could make some further optimizations with user agent detection. In the event that we don't know your device by its user agent, we'll still render all breakpoints on the server. But if we are certain you are on a device that only ever needs a subset of the breakpoints, we only render those on the server. This saves a bit of rendering time; more importantly it reduces the number of bytes sent over the wire.

We aren't doing any detection of desktop browsers. They are more resizable than mobile browsers, and we are more concerned with mobile users getting less content sent over their 3G connection.

https://artsy.github.io/blog/2019/05/24/server-rendering-responsively/#Tool.3:..code..artsy.detect-responsive-traits..code.

redbar0n avatar Mar 30 '21 18:03 redbar0n

CSS media queries (instead of JS-based screen measurements) might not be the way to go, at least not with React Native Web (RNW). Since:

  • RNW have dropped support for the className prop. See: https://github.com/necolas/react-native-web/issues/1318#issuecomment-661963508

  • Necolas, the creator of RNW is very negative towards CSS media queries:

SSR techniques don't generate media queries either. The only good thing about CSS media queries is that a SSR response doesn't need to know anything about the viewport dimensions. The problem with CSS media queries is how little you can do with them in the first place since they have no relation to the DOM (unlike JS media queries). They're completely deficient when it comes to creating dynamic apps that adapt to their environment, supporting everything from a portrait phone to a widescreen desktop screen. Even using client hints it's pretty complicated to get a SSR web app to render as if it were in the browser. At the moment there is probably no benefit for SSR of a React app, because you pay the cost of rendering on both the server and the client. The initial response isn't even interactive. Plus, using a PWA architecture would let you cut out the server roundtrip for assets anyway.

https://github.com/necolas/react-native-web/issues/1688#issuecomment-665939373

Btw, Dripsy just dropped Fresnel (and with it, support for SSR), since it was "built on top of many hacks, all of which are entirely circumventing the recommendations of react-native-web", and "supporting SSR means the web API is complex, kind of confusing, and adds more DOM nodes."

redbar0n avatar May 28 '21 17:05 redbar0n

@redbar0n I tried many approaches to make this work. But it seems react-native-web and react-native are not yet ready for responsive props. So I am thinking to drop the responsiveness feature for now and wait for official support from styled-components or emotion.

Btw we will be using styled-components for version 2 :)

jsartisan avatar May 29 '21 10:05 jsartisan

To allow responsiveness, we can export some utility to functions that will serve the purpose.

jsartisan avatar May 29 '21 10:05 jsartisan

what was your experience with react-native-media-query?

It claims to enable responsiveness even with SSR..:

This package also works with next.js static generation or server-side rendering [SSR]. Since react-native-media-query creates css based media queries on web, it allows you to easily avoid flash of unstyled (or incorrectly styled) content on initial load.

Even though RNW dropped support for the className prop, it supports the dataSet prop, which react-native-media-query seems to use.

redbar0n avatar May 30 '21 10:05 redbar0n

It seems that using styled-components, as a CSS-in-JS solution, together with React Native Web + responsivity, is very problematic (as others have already experienced).

  • styled-components outputs all styles to the className prop. But RNW has deprecated all external uses of className prop (since RNW overwrites it).

  • styled-components/native doesn't support media queries for native, and likely won't for the foreseeable future, as they have already been negative towards that for a while: #203, and a PR that stagnated #489, though people keep requesting it #3141...

Overall:

  • RNW supposes to take control over the entire styling, with it’s own CSS-in-JS solution, StyleSheet. That exposes only a subset of CSS, to remove a few CSS footguns.

  • If you use RNW, what you likely want, is one uniform styling API across both Native and Web. To not duplicate code. StyleSheet is that API today. You could forgo it entirely on web, and only use something like styled-components. But then users would have two competing styling solutions exposed to them, and have to style twice (once for native, once for web). The other option, completely abandoning RNW’s built-in StyleSheet on native, in favor of styled-components/native, seems a riskier choice (and might also have some perf implications).

redbar0n avatar Jun 06 '21 17:06 redbar0n

I've done some more research into this. FWIW, please see: https://github.com/nandorojo/dripsy/issues/100#issuecomment-857620297

redbar0n avatar Jun 09 '21 11:06 redbar0n