What Is The Render Props?
Tags: react, javascript, frontenddeveloper
Published: 2018-03-18 02:12:10

---
title: What Is The Render Props?
published: true
description: this is one of the API of React.js.
tags: React.js, javascript, front-end-developer
---

I guess you might have heard about Render Props because React team wrote a article in blog [like this](https://reactjs.org/docs/render-props.html).

This is really helpful for me to understand how to use render props though, it might be a little bit hard for people to understand how to use it in depth.

So this time, I'm gonna describe how to use Render Props concisely.

Example Code which I will use for describing is [here](https://github.com/takahiro-saeki/react-new-api-examples).

## 2 types of Render props APIs.
I think there are 2 types of APIs which you can use it as a render props.
First case is **to use it as a props in props**.
Take a look at example.

```jsx
// src/containers/App/index.jsx

import React, { createContext } from 'react';
import List from '../../Components/List';

const App = () => (
  <List
    apiPath="//dog.ceo/api/breeds/list/all"
    render={
      ({list, isLoading}) => isLoading ? <div>now loading...</div> : <div>Done!</div>
    }/>
)

export default App;
```

So, as you can see you can use in props as a props.
Key point is here
```jsx
render={
      ({list, isLoading}) => isLoading ? <div>now loading...</div> : <div>Done!</div>
    }
```

How do you use arguments like `list` and `isLoading` ? the answer is below!

```jsx
// src/components/List/index.jsx
import React, { Component } from 'react';

export default class List extends Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [],
      isLoading: false
    }
  }

  fetchApi = async () => {
    const res = await fetch(this.props.apiPath);
    const json = await res.json();

    await this.setState({
      list: json,
      isLoading: false,
    });
  }

  componentDidMount() {
    this.setState({ isLoading: true }, this.fetchApi);
  }

  render() {
    return this.props.render(this.state)
  }
}
```

Especially, this line.
```jsx
  render() {
    return this.props.render(this.state)
  }
```

So, solution is easy, you need to add object as a arguments in `this.props.render()` in return method which is going to be returned.
You must be remember that `list` and `isLoading` arguments are state in `List` component.

if you add something key and property in state in `List` component, you can be used property as a argument from state.
of course, if state is changed, arguments params will be changed.

It's not necessary to add state object in `this.props.render()` function. but I think you would better add state. The more you use it as a render props `component` or `utils`, you would better do it.


## this.props.children's case
On the other hand, you can make use of other type of render props by using `this.props.children()` !

Let's take a look at below's example.

```jsx
// src/containers/ChildRender

import React, { Component } from 'react';
import Counter from '../../Components/Counter';

const ChildRender = () => (
  <Counter>
    {({count, increment, decrement, incrementAsync, incrementAsyncTen}) => (
      <section>
        <div>count: {count}</div>
        <button onClick={increment}>+</button>
        <button onClick={decrement}>-</button>
        <button onClick={incrementAsync}>incrementAsync</button>
        <button onClick={incrementAsyncTen}>incrementAsyncTen</button>
      </section>
    )}
  </Counter>
)

export default ChildRender;
```

You might understand what's going on.

I guess it's easy for you to take a look at code of `Counter` component.

```jsx
// src/components/Counter

import React, { Component, cloneElement, Fragment } from 'react';

export default class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      increment: this.increment,
      decrement: this.decrement,
      incrementAsync: this.incrementAsync,
      incrementAsyncTen: this.incrementAsyncTen
    }
  }
  
  increment = () => {
    this.setState(state => ({count: ++state.count}))
  }
  
  decrement = () => {
    this.setState(state => ({count: --state.count}))
  }
  
  incrementAsyncTen = () => {
    setTimeout(
      () => this.setState(state => ({count: state.count + 10})), 
      1000
    )
  }
  
  incrementAsync = () => {
    setTimeout(
      () => this.setState(state => ({count: ++state.count})), 
      1000
    )
  }
  
  render() {
    const { children } = this.props;
    return children({...this.props, ...this.state})
  }
}
```

This is pretty easy to understand! and I think it looks similar with [HOC Pattern](https://reactjs.org/docs/higher-order-components.html).
You would prepare method which you make use of it as a argument from `Counter` component in Container or somewhere where you use it.

Finally, you need to render `this.props.children()` ! but, you need to add props and state or object which you want to add in argument!

Thats's it!

If you are interested in these example, again example is [here](https://github.com/takahiro-saeki/react-new-api-examples).
please check it out!

Next time, I'm supposed to describe how to use portals API for React.js!

Thank you for reading! haaaaaaaaave a nice day!