DEV Community

Omar Alshaker
Omar Alshaker

Posted on • Updated on

The True Delight of React’s Error and Warning Messages

Photo by [Štefan Štefančík](https://unsplash.com/@cikstefan) on [Unsplash](https://unsplash.com/photos/pzA7QWNCIYg?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)Photo by Štefan Štefančík on Unsplash

Introduction

There is this fascinating idea that hasn’t left me for years now, that software developers, with all their prejudices, biases, and humanness in general, shape the world around us.

Think about it. Software, just like music, is an intangible good. It’s not wine or chocolate where raw materials can limit the product quantity then the number of people who enjoy it. There exists thousands of software pieces that are written by individuals on a Saturday night and are used by millions of people everywhere.

It’s fair to say that those individuals have an impact, small or big, on people’s lives. And even if we consider corporations, the number of people who produce software is a microscopic number in relation to the number of said software users. For instance, Google has ~18K engineers worldwide, while around 1.17 billion people use Google, that’s a ratio of 0.000015%. We can see the huge dependence on software developers’ opinions and ideas to shape the world. There is obviously a developer society and a sub-culture. And if a meme or an idea spreads in this society, it would inevitably shape the technology used by everyone.

Now imagine, in a sci-fi kind of way, that there is an imaginary software technology that solves a world problem. Say it can cure cancer or completely eliminate poverty. But, this technology has the cost of ruining the life of the software developer who uses it. Would that technology ever see the light? Hardly. This imaginary story is an extreme example of the conflict of interest between the software developer and the end user. If good software meant the developer being uncomfortable, we will not see good software. And a big part of software developers’ lives is error messages. They’re key to the experience, and paying attention to them goes a long long way. They are directly important to the developer, and indirectly important to everyone of us.

React

Of all the libraries and packages I’ve used in the last ~10 years, I haven’t seen a library where errors and warnings are as beautiful. Developers, including me, usually try to detect errors that break their own code and report them to the user along with the data they have on hand (scope?). Maybe mention the most common mistake that can cause the error along with an automatically-generated stack trace and that’s it.

TypeError: undefined is not an object
Enter fullscreen mode Exit fullscreen mode

But with React, the library works overtime trying to guess for you what went wrong. The error guessing effort is quite obvious and it’s tremendously helpful; it saves you a lot of time debugging and tries its best to save your day.

To help you enjoy the experience like I do writing React apps, I’ll make this article a ride. I’ll show React snippets with mistakes in them, you may try to find the issue or just look at the warning/error below and decide whether it would be helpful for you. This is not to list every message React logs. It’s a very small sample for inspiration.

Let’s start!

1. A simple one

class MyComponent extends React.Component {
  componentWillMount() {
    console.log('Component mounted!')
  }
}
Enter fullscreen mode Exit fullscreen mode

What’s wrong with this component?

Here is the message:

Warning: MyComponent(…): No `render` method found on the returned component instance: you may have forgotten to define `render`.
Enter fullscreen mode Exit fullscreen mode

Beautiful, isn’t it? The component name and a correct suggestion. Super easy to fix.

2. A trickier one

class MyComponent extends React.Component {
  componentDidUnmount() {
    console.log('Unmounted!');
  }
  render() {
    return <h1>Hi!</h1>
  }
}
Enter fullscreen mode Exit fullscreen mode

What’s the issue here?

Here is the message:

Warning: MyComponent has a method called componentDidUnmount(). But there is no such lifecycle method. Did you mean componentWillUnmount()?
Enter fullscreen mode Exit fullscreen mode

React went out of its way here. It expected you to make this mistake and waited for you there. Silence wouldn’t break React in this case, it would only break your app. Quite sympathetic of the library.

3. A little obvious one

class GreetingComponent extends React.Component {
  constructor() {
    super();
    this.state = {name: 'Omar'};
  }
  render() {
    this.setState({name: 'Not Omar'});
    return <div>Hi {this.state.name}!</div>
  }
}
Enter fullscreen mode Exit fullscreen mode

What’s the issue?

Here is the warning:

Warning: Cannot update during an existing state transition (such as within `render` or another component’s constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.
Enter fullscreen mode Exit fullscreen mode

4. Not quite obvious

class MyComponent extends React.Component {
  constructor() {
    super();
    this.setState({name: 'John'});
  }
  render() {
    return <h1>Hi {this.state.name}!</h1>
  }
}
Enter fullscreen mode Exit fullscreen mode

What’s the issue?

Here is the message:

Warning: setState(…): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op.

Please check the code for the MyComponent component.
Enter fullscreen mode Exit fullscreen mode

5. Pure elegance


const type = true;

ReactDOM.render( 
  <input type={type} />,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

What’s wrong with type here?

Here is the warning:

Warning: Received `true` for non-boolean attribute `type`. If this is expected, cast the value to a string.
 in input
Enter fullscreen mode Exit fullscreen mode

And that’s another example of an error that doesn’t affect React, rather affects your app.

6. The beginner’s rescuer

class greetingComponent extends React.Component {
  render() {
    return <h1>Hi!</h1>
  }
}

ReactDOM.render( 
  <greetingComponent />,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

The two warnings:

Warning: <greetingComponent /> is using uppercase HTML. Always use lowercase HTML tags in React.

Warning: The tag <greetingComponent> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
Enter fullscreen mode Exit fullscreen mode

I definitely fell for this at least once.

7. OK I fixed it, but it still doesn’t work

class GreetingComponent extends React.Component {
  render() {
    return <h1>Hi!</h1>
  }
}

ReactDOM.render( 
  GreetingComponent,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

What’s wrong now?

The message:

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
Enter fullscreen mode Exit fullscreen mode

Yup, it should be:

ReactDOM.render(<GreetingComponent />, document.getElementById("root"));
Enter fullscreen mode Exit fullscreen mode

8. A very common mistake in the first couple days


class GreetingComponent extends React.Component {
  render() {
    return <h1 class="bold">Hello!</h1>
  }
}

ReactDOM.render( 
  <GreetingComponent />,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

What’s up here?

The message:

Warning: Invalid DOM property `class`. Did you mean `className`?
 in h1 (created by GreetingComponent)
 in GreetingComponent
Enter fullscreen mode Exit fullscreen mode

Enough data to land you exactly at your mistake

9. Why don’t you come back? 🎼


class GreetingComponent extends React.Component {
  render() {
    <h1>Hello!</h1>
  }
}

ReactDOM.render( 
  <GreetingComponent />,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

You said goodbye
I was trying to hide what I felt inside
Until you passed me by
You said you’d return
Will you ever return? 🎵

Uncaught Error: GreetingComponent(…): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
Enter fullscreen mode Exit fullscreen mode

10. And the one that doesn’t need an example:

You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Enter fullscreen mode Exit fullscreen mode

This one is a personal favorite.

Obviously, I haven’t used every framework and library ever existed. And there may be better examples of nice and helpful error messages. But as a frontend developer, I can safely say that React easily stands out. I’ve been inspired by it and now I am trying my best to guess the areas my code users could make mistakes, and provide them with eleborate and helpful error messages when they do. For I am a true believer that a better developer experience means a better world.

If you know some other nice examples of React warnings, please feel free to mention them in the comments and I’ll add them.

This was also published on Medium.

Top comments (3)

Collapse
 
oenonono profile image
Junk • Edited

Some important history. Error has a specific meaning in general and in JavaScript and a fraught history on the web platform. React explicitly labels many of its errors you demonstrated as warnings. This is intentional and means something. An error is the highest level of problem. An error is something you throw in JavaScript and not all that long ago, an error would halt further JavaScript execution in IE without try/catch, which was simultaneously too abysmally slow to use. The web platform has long been a "forgiving" one, in part because "real programming languages" were an afterthought. It was a platform for users more than for developers and web browsers correspondingly went out of their way to make their best attempt with whatever code they were given. There are numerous syntactic mistakes a web browser will accept, parse, automatically correct or partially discard, and still spit out a functional web page. Once upon a time, as developers became a louder voice and larger base, draconian error handling was introduced to the web for the next generation web, envisioned as being XML-based. Stop spending developer time and processing cycles trying to be forgiving, people said. Instead, be specific about what the problem is so that the developer who caused the problem can fix it. After all, it was difficult to track down the cause of unexpected results from browsers' automatic corrections. But this was a bad experience for users, who could now be greeted with a web page that was just one big error. So effort instead went into more robust developer tooling in browsers, which developers could then make use of, and into improving JavaScript, and into JavaScript frameworks. Which made (and continue to make) their own mistakes in this respect. Contrast React with Angular 1. Many Angular 1 errors would interrupt application functionality entirely. While Angular went to the trouble of carefully crafted messages, elaborate stack traces, and even links for more information on each error, they nevertheless still mostly lacked specific information or examples that would help track down the root cause of a problem. Most errors were errors, the highest severity. It was mostly unforgiving, frequently draconian, and rarely improved user experience. It was, however, more like what programmers were used to. Its familiarity made it preferable to some web developers. Next, React. React provides warnings that attempt to forgive, continue to render a functional application, and yet give specific and actionable information to a developer. This is a huge improvement in JS frameworks and addresses the real developer issues caused by the way browsers work while not discarding the good parts in and reasons why browsers work that way. But does it, by necessity in its JavaScript runtime, also have errors that would result in broken experiences for users? How do you prevent that? What about the app you're writing? What did you learn from React's errors about error experiences for your app's users? Because that's the most important part of whole thing. It's the reason we get paid. Better end user experience means a better world. Better developer experience is just a means of getting there.

Collapse
 
swyx profile image
swyx

react has the benefit of hundreds of developers manually adding warnings to it. this is unfortunately unlikely to scale because most projects dont have the popularity of react. for 99% of projects, better to make it part of the language, and use something like typescipt.

Collapse
 
wolverineks profile image
Kevin Sullivan

How do these react warnings compare to the corresponding warnings provided by flow and typescript?