# Render Props

## A Simple Render Props Example

Example of rendering props.

{% tabs %}
{% tab title="App.js" %}

```jsx
import React from "react"
import Example from "./Example"

function App() {
    return (
        // Component rendering the prop 
        <div>    
            <Example renderProps = {
                function(name, bool){
                    return(
                        <h1>Hello {name}, {bool ? "Good Morning" : "Good Night"}</h1>  
                    ) 
                }
            } 
            />
        </div>
    )
}

export default App
```

{% endtab %}

{% tab title="Example.js" %}

```jsx
import React from "react"

function Example(props){
    return(
        // Calling the function inside the rendered prop
        <div>
            {props.renderProps("Sarah", false)} 
        </div>
    )
}

export default Example
```

{% endtab %}

{% tab title="index.js" %}

```jsx
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"

ReactDOM.render(<App />, document.getElementById("root"))
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
&#x20; A component with a **render prop** takes a function that returns a React element and calls it instead of implementing its own **render** logic.
{% endhint %}

## Sharing State with Render Props

We can use Render Props to **achieve DRY principle** & **share logic** between different components.

{% tabs %}
{% tab title="Favorite.js" %}

```jsx
import React, {Component} from "react"
import Toggler from "./Toggler"

function Favorite() {
    return (
        // Rendering a prop within a functional component
        <Toggler render = {
        
            // Props function recieving arguments
            function(on, toggle){
                return(
                    <div>
                        <h3>Click heart to favorite</h3>
                        <h1>
                            <span 
                                onClick={toggle}
                            >
                                {on ? "❤️" : "♡"}
                            </span>
                        </h1>
                    </div>    
                )
                
            }
        }
        />
        
    ) 
}

export default Favorite

```

{% endtab %}

{% tab title="Menu.js" %}

```jsx
import React from "react"
import Toggler from "./Toggler"

function Menu(props) {
    return (
        // Rendering a prop within a functional component & passing the 'state' of that component 
        <Toggler defaultOnValue={true} render = {
            function(on, toggle){
                return(
                    <div>
                        <button onClick={toggle}>{on ? "Hide" : "Show"} Menu </button>
                        <nav style={{display: on ? "block" : "none"}}>
                            <h6>Signed in as Coder123</h6>
                            <p><a>Your Profile</a></p>
                            <p><a>Your Repositories</a></p>
                            <p><a>Your Stars</a></p>
                            <p><a>Your Gists</a></p>
                        </nav>
                    </div>    
                )
                
            }
        }
        />
        
    ) 
}

export default Menu
```

{% endtab %}

{% tab title="Toggler.js" %}

```jsx
import React, {Component} from "react"

class Toggler extends Component {
    // Initializing component's state
    state = {
        on: this.props.defaultOnValue
    }
    
    // Assigning fallback/default state
    static defaultProps = {
        defaultOnValue: false
    }
    
    // Class method
    toggle = () => {
        this.setState(prevState => {
            return {
                on: !prevState.on
            }
        })
    }
    
    render() {
        return(
            // Calling the function inside the rendered prop & passing arguments
            <div>
                {this.props.render(this.state.on, this.toggle)}
            </div>    
        )   
    }
}

export default Toggler
```

{% endtab %}

{% tab title="index.js" %}

```jsx
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"

ReactDOM.render(<App />, document.getElementById("root"))
```

{% endtab %}
{% endtabs %}

## Render Props with React Children&#x20;

Another way we can render props is through using react `children`. In this case we don't have to specify the Prop within the Component.

{% tabs %}
{% tab title="DataFetcher.js" %}

```jsx
import React, {Component} from "react"

class DataFetcher extends Component {
    state = {
        loading: true,
        data: null
    }
    
    componentDidMount() {
        fetch(this.props.url)
            .then(res => res.json())
            .then(data => {
                this.setState({
                    data: data, 
                    loading: false
                })
                console.log(data)
            })
    }
    
    render() {
        return (
            this.props.children(this.state.data, this.state.loading)
        )
    }
}

export default DataFetcher
```

{% endtab %}

{% tab title="App.js" %}

```jsx
import React from "react"
import DataFetcher from "./DataFetcher"

function App() {    
    return (
        <div>
            <DataFetcher url="https://swapi.dev/api/people/1/">
                {(data, loading) => {
                    return (
                        loading ? 
                        <h1>Loading...</h1> :
                        <p>{JSON.stringify(data)}</p>
                    )
                    
                }}
            </DataFetcher>
        </div>
    )
}

export default App
```

{% endtab %}

{% tab title="index.js" %}

```jsx
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"

ReactDOM.render(<App />, document.getElementById("root"))

```

{% endtab %}
{% endtabs %}
