Using render callbacks to connect non-connected components in React
Tags: react, javascript, renderprops, rendercallbacks
Published: 2018-08-14 17:03:36

---
title: Using render callbacks to connect non-connected components in React
published: true
description: Tighten up your rendering skills using render callbacks, by harnessing the power of composition, to connect together, non-connected components.
tags: react, javascript, render-props, render-callbacks
cover_image: https://thepracticaldev.s3.amazonaws.com/i/pnd2ahcu88fjxfp7edes.jpg
---

The difference between a connected and a non-connected component, is that a connected component is subscribing to some kind of state, whereas a non-connected component has no awareness of any state, therefore "dumb."

When developing scalable applications, you're more likely to create non-connected, "dumb" components, which may subsequently need to subscribe to some kind of state, like you would from a Redux store.

Let's imagine an ecosystem of components that make up a ticketing sales website. Many small components make up the application, but we'll focus on one: A module in the sidebar that shows the top ticket sales of the hour. The footer also has a module that shows the same data (It's actually the same exact module, we've just rendered a second instance of it). Both of these components are being instantiated from different places, but they require the same data. Both are dumb and both require data in order to render.

The idea behind a "provider" component would be to provide values. For example, we can create a functional component that takes a function as its child, and when called back, returns a property named data, that is an empty array. if you're unfamiliar with the concept of render callbacks, read my previous article, [Power up your renders with render callbacks in React](https://dev.to/moimikey/power-up-your-renders-with-render-callbacks-in-react-47i5).

```jsx
const Provider = (props) => {
	const data = []
	return props.children({ data })
}
```

With the above, we can use it the way we would use a render callback:

```jsx
<Provider>
	{({ data }) => <MyComponent data={data} />}
</Provider>
```

What we've done is simply wrap our component within this `Provider` component, which will provide data, for the inner component (MyComponent) to use. Data can be anything we want, and come from anywhere. The provider can be renamed something else to be more descriptive:

```jsx
<TopSalesByHour>
	{({ data }) => <Tickets data={data} />}
</TopSalesByHour>
```

The above provider simply acts as a state machine and provides state to its children, in the above case, `Tickets`. We can go a step further and provide a loading interface to `Tickets`, as we may want to wait for data before actually rendering `Tickets`:

```jsx
<TopSalesByHour>
	{({ data }) => data ? <Tickets data={data} /> : <Loading />}
</TopSalesByHour>
```

What makes the above powerful, is that we've abstracted the data away from our view logic. We've also provided a scalable way to provide state to a stateless component. Lastly, we've provided our component the ability to conditionally render, based on that state.

We can go another step further into a scenario where we may want to provide multiple streams of data to a subscriber. In this case, not only do we want the `Top Sales By Hour`, but also `Top Sales By Day`. How can we "compose" these two providers?

```jsx
/*
 * We need to combine both of these...
 */
<TopSalesByHour>
	{({ data }) => data ? <Tickets data={data} /> : <Loading />}
</TopSalesByHour>

/*
 * into one
 */
<TopSalesByDay>
	{({ data }) => data ? <Tickets data={data} /> : <Loading />}
</TopSalesByDay>
```

In order to do this, we need to create a helper function. Javascript isn't magic (sometimes it is). This helper function is going to accept providers as arguments and combine them into two readable values. Let's first visualize how we'd use the component:

```jsx
<TopSales>
	{({byHour, byDay}) => (
		<React.Fragment>
			<Tickets data={byHour} />
			<Tickets data={byDay} />
		</React.Fragment>
	)}
</TopSales>
```

In the above case, rather than naming our variable `data`, we've given it a more descriptive name of what the data point actually is, since we're now going to compose both `TopSalesByHour` and `TopSalesByDay` by creating a `TopSales` component, which will combine the two:

```jsx
const Create = (jsx, container) => (...containers) => ({ children }) => {
  const wrap = props =>
    typeof children === "function" // For react, in preact this is an array.
      ? children(props)
      : children.map(fn => fn(props));

  const gatherComponents = (parent, ...rest) => {
    const child =
      rest.length === 0
        ? props => jsx(container, null, wrap(props))
        : gatherComponents(...rest);

    return outerProps =>
      jsx(parent, outerProps, innerProps =>
        jsx(child, Object.assign({}, outerProps, innerProps))
      );
  };

  return gatherComponents(...containers)();
};
```

The above function was borrowed from `render-prop-composer` by mini-eggs. I like this one because of its simplicity. Let's use it and then explain how it works:

```jsx
const composer = Create(React.createElement, React.Fragment)
const TopSales = composer(TopSalesByHour, TopSalesByDay)
```

As simple as that, we're now able to combine both `TopSalesByHour` and `TopSalesByDay` into a single `TopSales` component, whos sole purpose is just to feed us ticket data:

```jsx
<TopSales>
	{({byHour, byDay}) => (
		<React.Fragment>
			<Tickets data={byHour} />
			<Tickets data={byDay} />
		</React.Fragment>
	)}
</TopSales>
```

But how exactly does the code work? Let's explore.

```jsx
const Create = (jsx, container) => (...containers) => ({ children }) => {
  const wrap = props =>
    typeof children === "function" // For react, in preact this is an array.
      ? children(props)
      : children.map(fn => fn(props));

  const gatherComponents = (parent, ...rest) => {
    const child =
      rest.length === 0
        ? props => jsx(container, null, wrap(props))
        : gatherComponents(...rest);

    return outerProps =>
      jsx(parent, outerProps, innerProps =>
        jsx(child, Object.assign({}, outerProps, innerProps))
      );
  };

  return gatherComponents(...containers)();
};
```

The first thing to note with the above `Create` function, is that the first thing it does is return a function. This is why upon first use, we're setting up the function to use `React.createElement` and `React.Fragment`. I actually admire the author of the function for keeping the code agnostic and dependency free, whereby we're passing React functions for it to use internally. As you read further, the variable `jsx` will refer to `React.createElement` and `container` will refer to `React.Fragment`.


```jsx
const composer = Create(React.createElement, React.Fragment)
const TopSales = composer(TopSalesByHour, TopSalesByDay)
```

When we subsequently pass the components that we want to compose, `gatherComponents` is called, using its arguments: `TopSalesByHour` and `TopSalesByDay`.

```jsx
gatherComponents(...containers)();
```

It's within the above method that the magic happens:

```jsx
  const gatherComponents = (parent, ...rest) => {
    const child =
      rest.length === 0
        ? props => jsx(container, null, wrap(props))
        : gatherComponents(...rest);

    return outerProps =>
      jsx(parent, outerProps, innerProps =>
        jsx(child, Object.assign({}, outerProps, innerProps))
      );
  };
```

Remembering that `jsx` is referring to `React.createElement`, the above code is returning another function (this is important) which is responsible for creating a new component (`TopSales`) and assigning it the props of each (`...rest`) component passed as arguments to `composer` (`const TopSales = composer(TopSalesByHour, TopSalesByDay)`).

Also, notice that `gatherComponents` is being called inside itself, denoting that this is a recursive function, whereby `rest.length === 0` is the base case.

As `gatherComponents` iterates over each of the composed `TopSales*` components, `outerProps` holds the value for each of the iterated components holding our props data, which is assigned to the final composed component (`TopSales`) we'll be using.

That's all! At first glance, this may be confusing to the novice developer, but I urge you to try out the code in the sandbox linked below. If it still proves a challenge, I recommend reading up on closures and recursion.

If you have any questions, comments, concerns, thoughts, please leave a comment below! Also, schedule a session with me on [Codementor](https://www.codementor.io/moimikey) and get your first 15 minutes free.

* * *

Try out the above psuedo code in real life on CodeSandbox: https://codesandbox.io/s/7j3pxr3xyq

References:
  * https://github.com/mini-eggs/render-prop-composer