React: Avoiding Gotchas

If you're new to React, you'll run into a few quirks that aren't immediately apparent. If you know what to watch out for, these head scratchers won't ruin your day.

Capitalized component names are enforced

React will throw an error if your component doesn't begin with a capital letter.

Warning: The tag timer is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

Easily correctable:

class Timer extends React.Component {}

JSX elements must be closed

Can't leave these open as we often do in HTML:

<br> <!-- no sir, try again -->
<br /> <!-- yes, proceed -->

HTML attributes in JSX can differ slightly

For the most part you can use what you know, but here are some exceptions/guidelines from the docs:

  • Everything is camelCased (just like DOM APIs)
<div className="macaroni"></div>
  • Style attribute accepts an object
{ backgroundColor: 'red' }
  • Because for is a reserved word in JavaScript, React elements use htmlFor instead
<label htmlFor="free"></label>

NO if/else statements in JSX

From the docs: If-else statements don't work inside JSX. This is because JSX is just syntactic sugar for function calls and object construction.

Dust off and forge ahead with a ternary expression instead:

{ condition ? 'applies if true' : 'applies if false' }

setState is an async function

When using setState to well, set some state, it's an asynchronous operation. You can take a look at this.state right after execution if you're skeptical. Good news is that setState will take a callback if you need an immediate action to follow:

this.setState(
  { title: 'Mars Attacks' },
  function() {
    // run for the hills
  }
)

Mutating from within render() is a no-go

React re-renders every time state changes, so it's intuitive that we shouldn't introduce any other changes during a render cycle. In an ideal world, React is fed some data and has everything it needs to render and wait for the next change. Forget the surprises.

this.props.children isn't always an array

React will return a single object if only one child exists.

<!-- inner stores as a single object -->
<div>
  <p></p>
</div>

<!-- inner stores as an array objects -->
<div>
  <p></p>
  <p></p>
</div>

This can be a bummer if you'd like to use handy array methods like map. Fortunately, we can coerce this.props.children into an array with a top-level API method:

React.Children.toArray(children)

Now treat yourself. 🍺 🌮