imagen

Render Props

Delegar lo que un componente va a renderizar a otro componente, normalmente a un padre en el árbol de componentes, cuando queremos dar mayor libertad a quien quiera utilizar un componente para indicar que es lo que se va a renderizar.

Se complementa muy bien con la composición de componentes.

De cierta forma se aplica el principio de inversion de responsabilidad (la D de SOLID) donde se "invierte" la responsabilidad de lo que se va a renderizar, pasando esta responsabilidad de estar en el componente mismo (hijo) a estar en el componente que lo implementa (padre).

Ejemplo 1

Componente Padre utilizando render props

En la implementación (padre) del componente TodoList se define como la propiedad onError que es una función que retorna un componente, lo mismo ocurre para onLoading, onEmptyTodos, onEmptySearchResults y render de esta forma es el padre quien determina que se va a renderizar cuando el hijo "imprima/renderice" esas propiedades.

Note que la propiedad onEmptySearchResults recibe un argumento que es utilizado en el resultado. Este argumento en particular puede ser definido por el padre o ser entregado por el componente hijo, segun el caso de uso.

<TodoList
  error={error}
  loading={loading}
  searchedTodos={searchedTodos}
  onError={() => <TodosError />}
  onLoading={() => <TodosLoading />}
  onEmptyTodos={() => <EmptyTodos />}
  onEmptySearchResults={
    (searchText) => <p>No hay resultados para {searchText}</p>
  }
  render={todo => (
    <TodoItem
      key={todo.text}
      text={todo.text}
      completed={todo.completed}
      onComplete={() => completeTodo(todo.text)}
      onDelete={() => deleteTodo(todo.text)}
    />
  )}
/>
Componente Hijo utilizando las render props

En el componente internamente manejar el renderizado de las props, pero el componente no necesita conocer el componente que se renderizara en cada prop, esta sera entregado y manejada directamente por el padre.

function TodoList(props) {
  return (
    <section className="TodoList-container">
      {props.error && props.onError()}
      {props.loading && props.onLoading()}

      {(!props.loading && !props.searchedTodos.length) && props.onEmptyTodos()}

      {props.onEmptySearchResults("valor buscado")}

      {props.searchedTodos.map(props.render)}

      <ul>
        {props.children}
      </ul>
    </section>
  );
}

Ejemplo 2

Componente Hijo

const style = {
  boton: {
    backgroundColor: 'purple',
    color: 'white',
  }
}
export default ({ children, ...rest }) => (
  <button style={style.boton} {...rest}>{children}</button>
)


#### Implementación (padre)
```javascript
<div>
  <Button onClick={(e) => {}}>Mi boton</Button>
</div>