react-native-magnus
react-native-magnus copied to clipboard
[Feature] Responsive Props
Since magnus works on web too, adding responsive props to handle media query both on web and mobile devices is must-have feature.
How would the High Level API be? Like Chakra UI's array syntax or something else?
We are trying to make the API similar to Chakra-UI.
any progress on this? dripsy have something similar https://github.com/nandorojo/dripsy
@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.
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.
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 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 :)
To allow responsiveness, we can export some utility to functions that will serve the purpose.
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.
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 theclassName
prop. But RNW has deprecated all external uses ofclassName
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).
I've done some more research into this. FWIW, please see: https://github.com/nandorojo/dripsy/issues/100#issuecomment-857620297