<p dir="auto">Applying the <a href="https://github.com/zeit/next.js/issues/219#issuecomment-258966784" data-hovercard-type="issue" data-hovercard-url="/vercel/next.js/issues/219/hovercard">proposed</a> <a href="https://github.com/zeit/next.js/pull/3229" data-hovercard-type="pull_request" data-hovercard-url="/vercel/next.js/pull/3229/hovercard">solutions</a> for <a href="https://github.com/zeit/next.js/issues/219" data-hovercard-type="issue" data-hovercard-url="/vercel/next.js/issues/219/hovercard">client-only modules</a> works for initial render, but any hot reload causes the client-only module to go become undefined.</p>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://github.com/zeit/next.js/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h2 dir="auto">Expected Behavior</h2>
<p dir="auto">Client-only modules re-render after a change is made to a relevant source file.</p>
<h2 dir="auto">Current Behavior</h2>
<p dir="auto">Client-only modules disappear from the rendered tree (potentially throwing an error); as the module is <code class="notranslate">undefined</code>.</p>
<h2 dir="auto">Steps to Reproduce (for bugs)</h2>
<ol dir="auto">
<li>Render a React component (parent) that relies on an client-only module (child). (example below)</li>
<li>Make a change to to the parent.</li>
</ol>
<h2 dir="auto">Context</h2>
<p dir="auto">I desire to server-render my Next.js application, sans components that require client technology (e.g. a component for a YouTube video player is not server-renderable). I also desire to hot reload changes to components while working in my development environment.</p>
<h2 dir="auto">Your Environment</h2>

<table role="table">
<thead>
<tr>
<th>Tech</th>
<th>Version</th>
</tr>
</thead>
<tbody>
<tr>
<td>next</td>
<td>4.2.3</td>
</tr>
<tr>
<td>node</td>
<td>8.9.4</td>
</tr>
<tr>
<td>OS</td>
<td>macOS 10.13.3</td>
</tr>
<tr>
<td>browser</td>
<td>Chrome 64.0.3282.140</td>
</tr>
</tbody>
</table>
<h2 dir="auto">Example</h2>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import React, { Component } from 'react';

let YouTube;

export default class VideoPlayer extends Component {
  constructor(props) {
    super(props);
    this.state = { renderYouTube: false };
  }

  // cDM is not invoked during a hot reload; which means YouTube is undefined
  // on any subsequent render.
  componentDidMount() {
    YouTube = require('react-youtube').default;
    this.setState({ renderYouTube: true });
  }

  render() {
    return (
      &lt;div&gt;
        {this.state.renderYouTube &amp;&amp; &lt;YouTube videoId={this.props.id} /&gt;}
      &lt;/div&gt;
    );
  }
}"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-v">React</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-v">Component</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'react'</span><span class="pl-kos">;</span>

<span class="pl-k">let</span> <span class="pl-v">YouTube</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-k">class</span> <span class="pl-v">VideoPlayer</span> <span class="pl-k">extends</span> <span class="pl-v">Component</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">super</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">state</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span> <span class="pl-c1">renderYouTube</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-c">// cDM is not invoked during a hot reload; which means YouTube is undefined</span>
  <span class="pl-c">// on any subsequent render.</span>
  <span class="pl-en">componentDidMount</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-v">YouTube</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'react-youtube'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">default</span><span class="pl-kos">;</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">renderYouTube</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-en">render</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-kos">(</span>
      <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
        <span class="pl-kos">{</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">state</span><span class="pl-kos">.</span><span class="pl-c1">renderYouTube</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-c1">&lt;</span><span class="pl-v">YouTube</span> <span class="pl-c1">videoId</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">props</span><span class="pl-kos">.</span><span class="pl-c1">id</span><span class="pl-kos">}</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span><span class="pl-kos">}</span>
      <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
    <span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">It is in my understanding that the <code class="notranslate">&lt;style jsx&gt;</code> tag contains an interpolated string in order allow insertion of variables that can be stored and manipulated in javascript as in the following example:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="const color = 'red';

return (&lt;div&gt;
    &lt;p&gt;Hello&lt;/p&gt;
    &lt;style jsx&gt;
    {`
        p {
            color: ${color};
        }
    `}
    &lt;/style&gt;
&lt;/div&gt;);"><pre class="notranslate"><code class="notranslate">const color = 'red';

return (&lt;div&gt;
    &lt;p&gt;Hello&lt;/p&gt;
    &lt;style jsx&gt;
    {`
        p {
            color: ${color};
        }
    `}
    &lt;/style&gt;
&lt;/div&gt;);
</code></pre></div>
<p dir="auto">I am trying to use the previous mechanism to encapsulate the media queries that I use in a single location:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="    const mediaQueries = {
        mobile: '@ media screen and (max-width: 320 px)',
        ...
    };"><pre class="notranslate"><code class="notranslate">    const mediaQueries = {
        mobile: '@ media screen and (max-width: 320 px)',
        ...
    };
</code></pre></div>
<p dir="auto">But when I try to use them as follows:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="return (&lt;div&gt;
    &lt;p&gt;Hello&lt;/p&gt;
    &lt;style jsx&gt;
    {`
        ${mediaQueries.mobile} {
            p {
                color: ${color};
            }
        }
    `}
    &lt;/style&gt;
&lt;/div&gt;);"><pre class="notranslate"><code class="notranslate">return (&lt;div&gt;
    &lt;p&gt;Hello&lt;/p&gt;
    &lt;style jsx&gt;
    {`
        ${mediaQueries.mobile} {
            p {
                color: ${color};
            }
        }
    `}
    &lt;/style&gt;
&lt;/div&gt;);
</code></pre></div>
<p dir="auto">I get the following error:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Module build failed: Error: /absolute_path/MediaQueryIssueExample/pages/index.js?entry: Nesting detected at 9:21. Unfortunately nesting is not supported by styled-jsx.
    at Function.disableNestingPlugin (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/lib/style-transform.js:22:13)
    at proxy (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:1311:30)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:804:14)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:366:17)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:366:17)
    at stylis (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:1458:16)
    at transform (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/lib/style-transform.js:120:3)
    at processCss (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/_utils.js:461:65)
    at PluginPass.exit (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/babel.js:232:51)
    at newFn (/absolute_path/MediaQueryIssueExample/node_modules/babel-traverse/lib/visitors.js:276:21)"><pre class="notranslate"><code class="notranslate">Module build failed: Error: /absolute_path/MediaQueryIssueExample/pages/index.js?entry: Nesting detected at 9:21. Unfortunately nesting is not supported by styled-jsx.
    at Function.disableNestingPlugin (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/lib/style-transform.js:22:13)
    at proxy (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:1311:30)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:804:14)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:366:17)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:366:17)
    at stylis (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:1458:16)
    at transform (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/lib/style-transform.js:120:3)
    at processCss (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/_utils.js:461:65)
    at PluginPass.exit (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/babel.js:232:51)
    at newFn (/absolute_path/MediaQueryIssueExample/node_modules/babel-traverse/lib/visitors.js:276:21)
</code></pre></div>
<p dir="auto">The <a href="https://github.com/MissaouiChedy/MediaQueryIssueExample">MediaQueryIssue repository</a> contains <strong>a minimalistic example that demonstrates the issue</strong>.</p>
<p dir="auto">The error message indicates that nested styling as been detected, this seems odd since I did use only one <code class="notranslate">&lt;style jsx&gt;</code> elements inside the rendered structure of the previous example.</p>
<p dir="auto">One of the advantages of using styled jsx is the ability to substitute values that can be manipulated in JavaScript in order to kill as much duplication as possible, unfortunately the fact that it is impossible to substitute media queries limits this advantage greatly.</p>
<p dir="auto">I suspect that this might be a <a href="https://github.com/zeit/styled-jsx">styled jsx</a> specific issue but I am not sure yet and I thought it would better to start the discussion here.</p>
<p dir="auto">Pointers to where to debug are welcome and I would be glad to contribute fixes if possible.</p>