question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Effective responsiveness

See original GitHub issue

For reasons such as efficiency (4) and SEO, we want to do server-side rendering in such a way that the response sent to the client is immediately usable without the need to re-render.

Alas our current solution, which essentially boils down to if/else branching per breakpoint, doesn’t fulfil these needs as it is practically impossible (1) to know what the breakpoint is that the client will want to display at SSR time.

Additionally, even when getting the initial breakpoint right, the performance of changing breakpoints will be worse when a browser has to evaluate JS, recalculate a component tree, diff DOM elements, and update the DOM; as opposed to the browser only needing to re-render the styling without any DOM changes. (2)

Example

Consider a desktop browser requesting a page that is rendered as follows:

<Responsive>
  {({ xs }) => {
    if (xs) {
      return <Box width={1} />
    } else {
      return <Box width={1/2} />
    }
  }}
</Responsive>

On the server we’ll render a xs version (because that’s currently our default), then once the browser receives the response it may start to render that version.

However, once React is fully booted it starts to render a virtual DOM version based on an actual media query that may result in a different breakpoint than xs. If that vDOM does not match what the server sent, the server version is thrown away and the new version is used instead.

Options

Note that these are just some bare-bones examples. Where possible it would be great to come up with prettier declarative APIs that use these techniques under the hood.

Pure CSS

In cases where all differences in layout can be expressed in styling, we should be able to do something like:

const ResponsiveBox = styled.div`
  @media screen and (max-width: 767px) {
    width: 100%;
  }
  @media screen and (min-width: 768px) {
    width: 50%;
  }
`

<ResponsiveBox />

When some components should only render on certain breakpoints, these may simply be hidden on those breakpoints using CSS. (3)

styled-system

We’re using styled-system, which out of the box comes with responsive options that, I assume–and we should verify this, do exactly what the above option does. For instance, rather than the above example, we should write <Box width={[1, 1/2]} />.

More…

Please suggest yours!

Notes

  1. That is, without resorting to added complexity such as sniffing user-agent and even then it won’t be foolproof.
  2. While this performance penalty is even noticeable on desktop machines, it’s even more important for mobile devices.
  3. In the case of mobile devices, this may lead to documents being sent to the client that include markup that will never be used, which presumably could add up for large pages. Seeing as in some of these cases, such as iPhones, we can pretty reliably determine the client never needs larger breakpoints, it would be great to have an API that could omit certain breakpoints completely.
  4. Besides the aforementioned re-rendering of the browser, there are also examples such as page caching, which could be done for all unauthenticated requests of some pages.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:45 (45 by maintainers)

github_iconTop GitHub Comments

3reactions
damassicommented, Oct 28, 2018

This renderOnlyAt pattern works well! One thing I noticed is we’ll need to use <MockBoot> in the tests and set initial breakpoints otherwise it will by default render out two (or however many) items.

3reactions
alloycommented, Oct 11, 2018

Alright, did a quick and dirty spike to verify my idea and it seems to work. These are the steps:

  • On the server we render markup for all breakpoints (in the future we’ll limit this for some user-agents).
  • The browser receives markup with proper media query styling and will immediately start rendering the expected visual result (for whatever viewport width the browser is at).
  • When all JS has loaded, React has booted, and starts rendering our app, we query the browser synchronously for what breakpoint it’s at and then we limit (using renderOnlyAt) the rendered components to the matching breakpoints.
  • Additionally, like we currently do with the Responsive component, we register event listeners with the browser to notify the MediaContextProvider when a different breakpoint is matched and then re-render the tree using the new value for renderOnlyAt.

I added logs to some components’ componentDidMount lifecycle methods that shouldn’t both be visible at the same time.

  1. The server renders all breakpoints and lifecycle methods such as componentDidMount will never be invoked, so all good:

    screen shot 2018-10-11 at 14 25 20
  2. The browser renders the markup, boots React and the app, which ends up only rendering for the currently matching breakpoint (lg) and thus yields a hydration error as expected, but importantly only mounts 1 component (LargeArtistHeader):

    screen shot 2018-10-11 at 14 25 09
  3. Resizing the browser window triggers re-renders at new breakpoints, again only mounting 1 component at a time (LargeArtistHeader, then SmallArtistHeader):

    screen shot 2018-10-11 at 14 25 47
Read more comments on GitHub >

github_iconTop Results From Across the Web

Responsiveness | Educational Skill Guide - Matter Slack App
Responsiveness is identified as one of Matter's top soft skills that is linked to performance, development, and career success.
Read more >
7 Ways To Be More Responsive To Your Customers - Forbes
7 ways to be more responsive to customers · 1. Ask your customers what they want. A survey of your existing customers can...
Read more >
effective responsiveness definition - Reverso Dictionary
1 productive of or capable of producing a result · 2 in effect; operative effective from midnight · 3 producing a striking impression;...
Read more >
Affective Responsiveness
Being able to respond to other family members with a wide range of emotions, appropriate for each situation, is a key to successful...
Read more >
Responsiveness: A Key Ingredient to Effective Sales Leadership
Responsiveness is absolutely essential for building trust, credibility, rapport, and loyalty with our direct reports. It also has very tangible ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found