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.

Request: Support For JSS-in-CSS in Server-Rendered Components

See original GitHub issue

JSS-in-CSS libraries are becoming more and more popular (e.g. styled-components with 18,000 stars at the moment). These libraries work by dynamically generating styles from within components and attaching these styles to the page via a dynamically generated (and updated) <style> tag. This works great out of the box for non-server-rendered components, however for server-rendered components this poses a problem, because in addition to the rendered HTML, the rendered styles also need to be attached to the page. Currently react-rails offers no API for this, and assumes that a component will return only its own rendered HTML from react_component().

There is a workaround of sorts as outline by @bakunyo in #864 which involves returning the rendered styles inside a <style> tag alongside the component’s HTML, then dynamically moving the <style> tag to the document <head> before the component is hydrated (which would otherwise result in the unexpected styles being discarded). For obvious reasons this is a very hacky fix and far from ideal.

It seems to me that some kind of additional API needs to exist to allow a component to render a <style> tag to the <head> of the document. Given that ReactRailsUJS.serverRender currently returns a string, could it also support returning an Array containing the component string as the first value and the styles as the second? If this second argument is present it could be rendered to the <head> via a helper.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:14
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
maximcommented, Jun 28, 2019

Here’s another experimental solution. It does not require creating custom helpers, or parsing strings. You just add an initializer into your rails app, which changes react-rails config. However it does use subclassing to provide modified classes to the configuration. Should work with both controller and view rendering. Feel free to use this as a basis for an official solution, or let me know if this is flawed somehow, would be super helpful. 👍

3reactions
schuylrcommented, Jun 21, 2019

I’ve created a new helper based on @bakunyo’s workaround that makes the usage a little more DRY:

  def styled_react_component(component, props, options, content_block_name)
    body = react_component(component, props, options)
    style = body.slice!(/<style.+style>/m)
    content_for content_block_name do
      style.html_safe
    end
    body.html_safe
  end

Then you can just call this in the ERB like this:

<%= styled_react_component 'App', {}, { prerender: true }, :head %>

I would say that it would probably be better to extend react_component to include an option similar to prerender: true like style_block: :head which would invoke the content_for when present.

With this, I think the only missing piece is somehow ensuring that ExecJS can return an array of strings, or a Ruby object that can be parsed for a body and style portion, with similar respective support for ReactRailsUJS.serverRender to allow us to return the DOM body and styles in a separated manner. That way, we can skip the slice! which is the only thing that seems hacky to me.

My ExecJS experience is limited (as much as my time) but I can try and make a PR for this later this summer if the approach above looks good.

Read more comments on GitHub >

github_iconTop Results From Across the Web

JSS integration with React
Install; Basic; Dynamic Values; Prefix classname; Theming; Accessing the theme inside the styled component; Accessing the theme without styles ...
Read more >
CSS-in-JS - ReactJS.NET
CSS-in-JS is a technique for declaring styles within components. ReactJS.NET supports server-rendered stylesheets for several libraries (pull requests ...
Read more >
Server rendering - Material UI - MUI
When the server receives the request, it renders the required component(s) into an HTML string, and then sends it as a response to...
Read more >
React Server Components with Next.js - Vercel
React Server Components improve the user experience of your application by pairing the best parts of server-rendering with client-side ...
Read more >
Styled-components vs. Emotion for handling CSS
Unlike other types of styling methods, the framework-agnostic approach does not require external plugins or additional setup. Emotion comes with ...
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