React
  • Introduction
  • Getting Started
    • Introduction
    • Before you get started
  • 1. Fundamentals
    • Introduction
    • Rendering
      • JSX
      • Exercise
      • Solution
    • Components
      • Stateless
        • Exercise
        • Solution
      • Stateful
        • Exercise
        • Solution
      • Styling
        • Exercise
        • Solution
        • Using CSS Modules
    • Folder Architecture
  • 2. Intermediate
    • Lifecycle methods
    • Controlled and Uncontrolled components
    • Anti-patterns
    • Refs and the DOM
    • Lifting State Up
  • 3. Advanced Topics
    • Conventions
    • Reconciliation
    • Performance Optimizations
      • Avoiding Reconciliation
      • PureComponent
      • Avoiding inline lambdas
      • Development vs Production build
    • Context
  • 4. Advanced Patterns
    • Higher-order Components
    • Children as Function
    • Renderless Components
    • Portals
    • Error handling
  • Exercises
    • Introduction
    • 1. ProductList light
      • Step 1
      • Step 2
      • Step 3
      • Step 4
      • Extra
      • Solution
Powered by GitBook
On this page
  1. 4. Advanced Patterns

Children as Function

PreviousHigher-order ComponentsNextRenderless Components

Last updated 6 years ago

In React, you can pass a function as children to a component:

<MyComponent>
  {() => {
    return "hello world!";
  }}
</MyComponent>

This technique is commonly referred to as render callbacks, and is used by many different libraries such as and . When applied, rendering logic can be kept in the owner component, instead of being delegated.

Here’s an example where we’ve created a component that automatically measures the size of it’s parent container and passes those parameters down to it’s children.

<AutoSizer>
  {(width, height) => (
    <div style={{width, height}}>
      This div will automatically adjust to the size of it's parent container
    </div>
  )}
</AutoSizer>

This prop is called the “render callback”. That function is able to receive parameters that will be assigned by the child the moment it is called, with the information the child has when doing its stuff. The child is the one to decide if it wants to call that function or not, again depending on its internal logic.

How it works Let’s look at how we might implement our previous example in a fairly naive way:

class AutoSizer extends React.Component {
  state = {
    width: 0,
    height: 0,
  }
  componentDidMount() {
    const node = ReactDOM.findDOMNode(this);
    const parentNode = node.parentNode;

    this.setState({
      width: parentNode.offsetWidth,
      height: parentNode.offsetHeight,
    });
  }
  render() {
    return this.props.children(this.state.width, this.state.height);
  }
}

When to use this pattern

  • Allows you to mix-and-match components

  • Which enables more modular (maintainable) code

  • As an alternative to context

Caveats Because of the no-inline-lambdas ESLint rule, children-as-function currently need to be written as such:

class ComponentThatConsumesAutoSizer extends React.Component {
  render(){
    <AutoSizer children={this.renderAutoSizerChildren} />
  }

  @autobind
  renderAutoSizerChildren(width, height) {
    return (
      <div style={{width, height}}>
        This div will automatically adjust to the size of it's parent container
      </div>
    );
  }
}

The children prop is commonly renamed, typically to render, so don’t be alarmed if you see a component using this naming convention.

Resources

Video Lecture

React Router
React Motion
https://courses.reacttraining.com/courses/advanced-react/lectures/3066347