Ink: React development error messages interfere with Ink output

Created on 28 Sep 2019  路  6Comments  路  Source: vadimdemedes/ink

When an error boundary's getDerivedStateFromError handler is called, React will print out a warning to the console like so:

The above error occurred in the <Example> component:
    in Example
    in ErrorBoundary
    in App

React will try to recreate this component tree from scratch using the error boundary you provided.

Because of this log output, it means that when the error boundary component is rendered _after_ the previous component, instead of overwriting it.

I put together a small example that hopefully explains this better:

// https://github.com/colinking/ink-testing/blob/master/src/error-boundaries.tsx
import React, { useState } from 'react'
import { render, Box, Color, useInput } from 'ink'

/**
 * See: https://github.com/vadimdemedes/ink/issues/234
 * 
 * Note: the output of this script depends on your terminal width. If you have enough space,
 * the ErrorBoundary (An error occurred: Whoops!) will overwrite the "React will try to..."
 * line entirely.
 * 
 * Output:
 *  Hit any key to crash!
 *  The above error occurred in the <Example> component:
 *      in Example
 *      in ErrorBoundary
 *      in App
 *  
 *  React will try to recreate this component tree from scratch using the error boundary you proAn error occurred: Whoops!
 * Expected:
 *  An error occurred: Whoops!
 */

interface ErrorBoundaryState {
  error?: Error
}

class ErrorBoundary extends React.Component<{}, ErrorBoundaryState> {
  state = {} as ErrorBoundaryState

  static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {
    return { error }
  }

  render() {
    const { error } = this.state

    if (!error) {
      return this.props.children
    }

    return (
      <Box>
        <Color>An error occurred: {error.message}</Color>
      </Box>
    )
  }
}

const Example: React.FC = () => {
  const [shouldError, setShouldError] = useState(false)
  useInput(() => {
    setShouldError(true)
  })

  if (shouldError) {
    throw new Error('Whoops!')
  }

  return (
    <Box>
      <Color green>Hit any key to crash!</Color>
    </Box>
  )
}

async function run() {
  const { waitUntilExit } = render((
    <ErrorBoundary>
      <Example />
    </ErrorBoundary>
  ), {
    debug: process.env.DEBUG === 'true',
  })
  await waitUntilExit()
}

run()

You can run this like so:

$ git checkout https://github.com/colinking/ink-testing.git
$ npm i
$ npx ts-node src/error-boundaries.tsx
docs enhancement shipped in v3

Most helpful comment

The reason it happens is because that The above error occurred in the <Example> component: is automatically written to stdout by React, it's not rendered as part of your Ink app. These warnings occur only when NODE_ENV is not set to production (similar to client-side apps).

So if you run your app with NODE_ENV=production, this message will go away:

$ NODE_ENV=production npx ts-node src/error-boundaries.tsx

All 6 comments

The reason it happens is because that The above error occurred in the <Example> component: is automatically written to stdout by React, it's not rendered as part of your Ink app. These warnings occur only when NODE_ENV is not set to production (similar to client-side apps).

So if you run your app with NODE_ENV=production, this message will go away:

$ NODE_ENV=production npx ts-node src/error-boundaries.tsx

I should add a section to readme describing the need to set NODE_ENV=production when distributing Ink-powered CLIs to end users.

Is there any way to disable this behavior without setting NODE_ENV=production? The issue is if you run other tools from an Ink app with that set, they may behave differently than you'd like (e.g. you may want NODE_ENV=test when using Ink to run a test suite to get the babel configuration correct).

@mAAdhaTTah I'm afraid not, it's not something Ink controls, it's in React's source code.

Interesting鈥搕his is better for Pastel, but maybe worth suggesting bundling into a compiled .js file such that it strips that stuff out in advance so it doesn't affect the final runtime.

Ink 3 is out with the fix for this issue included! Read the full announcement at https://vadimdemedes.com/posts/ink-3 :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zkat picture zkat  路  7Comments

cometkim picture cometkim  路  3Comments

asadm picture asadm  路  5Comments

gc picture gc  路  6Comments

zkat picture zkat  路  3Comments