DEV Community

hiro@
hiro@

Posted on

9 5

What Is The Render Props?

I guess you might have heard about Render Props because React team wrote a article in blog like this.

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.

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.

// 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

render={
      ({list, isLoading}) => isLoading ? <div>now loading...</div> : <div>Done!</div>
    }

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

// 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.

  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.

// 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.

// 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.
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.
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!

Sentry blog image

How to reduce TTFB

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

In this article, we’ll see how we can identify what makes our TTFB high so we can fix it.

Read more

Top comments (1)

Collapse
 
jalex profile image
Alex

What do you think about the use of props as 'public class fields' instead be passed to the method super(props) of the constructor as is show in this video??:

https:// egghead.io /lessons/egghead-use-class-components-with-react

hope read your answer :)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more