title: How to get Xterm.js resize properly?
body: <p><strong>tl;dr</strong>
  I've created a React wrapper to render an array of log messages into a terminal but resizing is giving a weird output (see screenshot). (There is a React-Wrapper on NPM but that wasn't working for my use-case - caused screen flickering)</p>
  
  <p>I'm working on a feature for Guppy where I'm adding <a href="https://github.com/xtermjs/xterm.js" rel="noreferrer">Xterm.js</a> for the terminal output.
  The PR can be found <a href="https://github.com/joshwcomeau/guppy/pull/355" rel="noreferrer">here</a>.</p>
  
  <p>I've added xterm because of hyperlink scanning/parsing and that is working.</p>
  
  <p>But I'm stuck with getting resize to work. If I'm starting the devServer in the app and wait for some text it will display with correct letter width.
  If I reduce the size I'm getting an output with an incorrect letter width. 
  Like in the following screenshot:
  <img src="https://user-images.githubusercontent.com/3046542/51803797-52e9d280-2259-11e9-9d27-5dba3ad4b505.png" alt="Messed output"></p>
  
  <p>It is always looking correct in the not resized state but after resize it will get the wrong display - so this will happen for enlarging &amp; shrinking the screen width.</p>
  
  <p>The output should look similar to the following screenshot (maybe with some wrapped lines):
  <img src="https://user-images.githubusercontent.com/3046542/51794649-b3d0c680-21d7-11e9-813c-f154bd593a39.png" alt="Correct output"></p>
  
  <p>I think this is caused by <a href="https://xtermjs.org/docs/api/addons/fit/" rel="noreferrer">Fit addon</a> or the way I'm handling resizing with the resize observer but I'm not sure.</p>
  
  <p>The span style of xterm letter are getting a width of <code>NaNpx</code> like in the following screenshot:
  <img src="https://i.stack.imgur.com/9NZZI.png" alt="CSS with width NaNpx">
  Is this caused by a media query I'm using? I haven't seen that yet maybe I have to temporarily disable all media queries to see if that's causing the behaviour. </p>
  
  <p>What I have tried so far:</p>
  
  <ul>
  <li>Wrapped <code>this.xterm.fit()</code> into a <code>setTimeout(func, 0)</code> but with-out an effect</li>
  <li>Modified some of the styles I'm using but I haven't found the cause.</li>
  </ul>
  
  <h1>Code</h1>
  
  <p>The code I'm using can be found on <a href="https://github.com/joshwcomeau/guppy/tree/feature-terminal-links" rel="noreferrer">Github branch feature-terminal-links</a> but here I'd like to extract the parts I've added to get Xterm to work with React:</p>
  
  <ol>
  <li>I created a styled-component <code>XtermContainer</code> as a div so I can add Xterm styles and own styling. The following code is inside <code>render</code> and will be our xterm.js container (<code>innerRef</code> will be used later in <code>ComponentDidMount</code> to intialize Xterm with that container):</li>
  </ol>
  
  <pre class="lang-js prettyprint-override"><code>&lt;XtermContainer
      width={width}
      height={height}
      innerRef={node =&gt; (this.node = node)}
  /&gt;
  </code></pre>
  
  <ol start="2">
  <li>Init xterm in <code>componentDidMount</code> with the container above:</li>
  </ol>
  
  <pre class="lang-js prettyprint-override"><code>componentDidMount() {
      Terminal.applyAddon(webLinks);
      Terminal.applyAddon(localLinks);
      Terminal.applyAddon(fit);
  
      this.xterm = new Terminal({
        convertEol: true,
        fontFamily: `'Fira Mono', monospace`,
        fontSize: 15,
        rendererType: 'dom', // default is canvas
      });
  
      this.xterm.setOption('theme', {
        background: COLORS.blue[900],
        foreground: COLORS.white,
      });
  
      this.xterm.open(this.node);
      this.xterm.fit();
  
      /* ... some addon setup code here (not relevant for the problem) ... */
  }
  </code></pre>
  
  <ol start="3">
  <li>Added <a href="https://www.npmjs.com/package/react-resize-observer" rel="noreferrer">react-resize-observer</a> inside of the wrapper that is also containing the terminal container so I can trigger <code>this.xterm.fit()</code> if the size changes (in the repo there is a <code>setTimeout</code> wrapper around for testing).</li>
  </ol>
  
  <pre class="lang-js prettyprint-override"><code>&lt;ResizeObserver onResize={() =&gt; this.xterm &amp;&amp; this.xterm.fit()} /&gt;
  </code></pre>
  
  <ol start="4">
  <li>Using <code>componentDidUpdate(prevProps, prevState)</code> to update the terminal and scroll the terminal to the bottom if the component is getting new logs:</li>
  </ol>
  
  <pre class="lang-js prettyprint-override"><code>componentDidUpdate(prevProps, prevState) {
      if (prevProps.task.logs !== this.state.logs) {
        if (this.state.logs.length === 0) {
          this.xterm.clear();
        }
        for (const log of this.state.logs) {
          /*
          We need to track what we have added to xterm - feels hacky but it's working.
          `this.xterm.clear()` and re-render everything caused screen flicker that's why I decided to not use it.
          Todo: Check if there is a react-xterm wrapper that is not using xterm.clear or 
                create a wrapper component that can render the logs array (with-out flicker).
          */
          if (!this.renderedLogs[log.id]) {
            this.writeln(log.text);
            this.xterm.scrollToBottom();
            this.renderedLogs[log.id] = true;
          }
        }
      }
  }
  </code></pre>
  
  <p>Ideas I have to find the cause:</p>
  
  <ul>
  <li><del>Check ResizeObserver code.</del> (see update below)</li>
  <li>Try to find why xterm css is getting a NaN width. Is Xterm.js using the style width of the container? If yes, maybe that's not correctly set.</li>
  </ul>
  
  <p><strong>Update</strong></p>
  
  <p>OK, the resize obeserver is probably not needed as I'm getting the same behaviour after commenting out the <code>&lt;ResizeObserver/&gt;</code> in render. So I think it's caused by xterm.js or the css in Guppy.</p>