React Holiday

Day 19: Decide not to decide

I know what my decision is,
Which is not to decide.

Indecision is the best tool you have for smooshing components together.

Master it.

Listen to Cinderella; leave a clue

I’ll just leave him a clue:
For example, a shoe.
And then see what he’ll do.

On the Steps of the Palace, Cinderella isn’t sure what to do. So she leaves a shoe as a clue and lets the prince decide what to do.

Let’s codify this masterful indecision.

class AClue extends React.Component {
  render() { return this.props.render('a shoe') }
}

const ThePrince = () =>
  <AClue
    render={clue =>
      <CheckEveryoneInTheKingdom clue={clue} />
    }
  />

If Cinderella were a React developer, she’d prefer render props.

A render prop

Simply, a render prop is indecision. React calls render() on a component which delegates to props.render.

The power is in the clues.

render() { this.props.render("a clue") }

A fairy-tail refactor of IdPager

Let’s refactor IdPager#render() to not-decide like Cinderella.

Start where we render the component. Give render as a prop— a function that takes a clue and returns a component.

Here, the clue clue is id and the return is a <Pokemon />.

ReactDOM.render(
  <IdPager render={id => <Pokemon id={id} />} />,
  document.getElementById("root")
);

Component-side, it’s simple as calling props.render with state.id.

<div>
  ...
  {this.props.render(this.state.id)}
</div>

Why though?

Using a component prop was great first step. It allowed us to uncouple the component specifics. But there remained a prop coupling around id.

With render props, we control all aspects of render.

<IdPager
  render={id =>
    <OtherComponent
      anotherWordForId={id}
      className="some-class-name"
    />
  }
/>

Tinker with it

Use the workspace below and explore render props.

Create a Character component that consumes the Star Wars API. Render a second IdPager that pages through Star Wars Characters.