Render Props en React: Una técnica para la reutilización de lógica 2025

Render Props en React: Una técnica para la reutilización de lógica 2025

juan correa

Juan Correa

Desarrollador de Software Senior

En este post vas a aprender qué es el patrón Render Props en React JS y cómo puedes utilizarlo para reutilizar lógica entre componentes.

Table of Contents

¿Qué es el Patrón Render Props?

De acuerdo a la documentación en React:

“Un componente con una render prop toma una función que devuelve un elemento de React y lo llama en lugar de implementar su propia lógica de representación.”

Lo anterior puede ser reformulado a: delegar la responsabilidad de hacer el render usando una función que el componente recibe por props.

Pero creo que la definición más clara es la de Michael Jackson, un gran contribuidor de la comunidad:

“A render prop is a function prop that a component uses to know what to render”.

Es decir: un render prop es una función que un componente usa para saber qué renderizar.

Vamos a ir viendo ejemplos en las siguientes líneas, pero antes es bueno tener en claro las ventajas, desventajas y en qué casos aplicar esta técnica.

¿Quieres dominar los Patrones de Diseño en React.js?

En mi ebook "Patrones avanzados en React.js", encontrarás más información sobre los patrones explicados en este post y contenido de alta calidad que te ayudará a llevar tus habilidades al siguiente nivel.

Descargar ebook gratis

Ejemplo de Render Props en vídeo

Si quieres ver un ejemplo aplicado en un proyecto del mundo real, te invito a darle play al siguiente vídeo donde explico cómo implementar el patrón Render Props en React JS paso a paso.

Si prefieres leer, sigue con el contenido a continuación.

Ventajas y desventajas de Render Props

Las principales ventajas al usar render props son:

  • Reusar código entre componentes haciendo componentes más reusables.
  • Flexibilidad en los componentes dejando abierto para su extensión y cerrado para su modificación (Principio Abierto - Cerrado).

Las principales desventajas al usar render props son:

  • Puede tender al anti patrón callback hell en estructuras de componentes complejas (un componente que use un render prop donde se use otro componente que use otro render prop, etc).

En qué casos aplicar Render Props

Utiliza los render props cuando:

  • Tengas un componente cuyo render va a ser dinámico, es decir, puede ser un render completamente diferente (en estructura de componentes, en visualización).
  • Quieras reusar lógica entre componentes usando un HOC. Si no quieres la complejidad que un HOC agrega a tu código, puedes usar render props como alternativa.

Ejemplo de Render Props en React

Vamos a ver un ejemplo que es muy común y que incluso vas a poder aplicar en tus desarrollos desde ya.

En una aplicación siempre hay que tomar en cuenta los buenos escenarios - donde todos estamos felices y la app funciona como esperamos - y los malos escenarios - donde el usuario da tres vueltas al cursor, da dos clicks y causa que la app explote por un error inesperado.

Desde la versión 16 de React contamos con maneras accesibles para manejar los errores controlando que nuestra app no se colapse solo porque una parte de ella tuvo una excepción.

Son llamados “Error boundaries” o límites de errores en español. Consideremos este código como ejemplo.

A continuación creamos un componente para poder controlar los límites de errores. Es un componente común y corriente de este tipo.

class ErrorBoundary extends Component {
  state = { hasError: false, error: null }
  componentDidCatch(error) {
    this.setState({ hasError: true, error })
  }
  render() {
    const { hasError, error } = this.state
    const { children } = this.props
    if (hasError) {
      return (
        <div>
          <p>Oops! ha ocurrido un error inesperado</p>
          {error.toString()}
        </div>
      )
    }
    return children
  }
}

Lo siguiente va a ser un componente cuya razón de existir es hacer que la app colapse o se “crashee”.

const MyBug = () => {
  const [isError, setIsError] = useState(false)
  const handleCrash = () => {
    setIsError(true)
  }
  if (isError) {
    throw new Error(':(')
  }
  return <button onClick={handleCrash}>Crashear la app</button>
}

Y así lo podemos utilizar.

export default function App() {
  return (
    <div className="App">
      <h1>Este es un componente destinado a crashear la app</h1>
      <ErrorBoundary>
        <MyBug />
      </ErrorBoundary>
    </div>
  )
}

Código disponible en este enlace: https://codesandbox.io/s/error-boundary-example-v959u?file=/src/App.js

En este ejemplo tenemos un componente ErrorBoundary que contiene la lógica necesaria para capturar un error en tiempo de ejecución y mostrar un mensaje alternativo en lugar de colapsar toda la app.

Nota: al ejecutarse este código transpilado en modo de desarrollo (como se ejecuta en el enlace), debido a la configuración de webpack, veremos el traceback del error con una cruz en la parte derecha para cerrarlo y ver la app.

Está muy bien pero:

  • ¿Qué pasa si queremos diferentes mensajes de error según el contexto de donde se aplique el ErrorBoundary?
  • ¿Hacemos N componentes de ErrorBoundary según el mensaje diferente?
  • ¿Llenamos de sentencias if/else dentro del render para mostrar un mensaje u otro?

Podríamos pasar por props el contenido del mensaje, pero eso no va a resolver si queremos agregar otros elementos como iconos o imágenes.

export default function App() {
  return (
    <ErrorBoundary message="esto no es suficiente">
      <MyBug />
    </ErrorBoundary>
  )
}

Nuestro objetivo es dejar abierto el componente para su extensión y cerrado a su modificación, es decir, no queremos modificar ErrorBoundary por cada caso de uso nuevo que tengamos.

Implementando Render Props

Vamos a refactorizar el componente ErrorBoundary para que pueda recibir un prop llamado render cuyo valor va a ser una función.

Cuando la app colapse, vamos a ejecutar el prop render.

Cabe aclarar que el nombre del prop normalmente es “render” o el prop “children”, pero no hay restricciones.

Cualquier prop que sea una función para indicar cómo hacer el renderizado, es un render prop.

class ErrorBoundary extends Component {
  state = { hasError: false, error: null }
  componentDidCatch(error) {
    this.setState({ hasError: true, error })
  }
  render() {
    const { hasError, error } = this.state
    const { children, render } = this.props
    if (hasError) {
      return render(error)
    }
    return children
  }
}

Nota: Estamos usando un componente tipo clase para poder usar el método componentDidCatch.

A continuación vamos a pasar el prop render como una función que retorne elementos JSX.

Para demostrar mejor la ventaja de usar render props, ahora colocamos dos veces los componentes de ErrorBoundary y MyBug para poder ilustrar cómo personalizar el render de cada elemento.

export default function App() {
  return (
    <div className="App">
      <h1>Este es un componente destinado a crashear la app</h1>
      <ErrorBoundary render={() => <h1>Hubo un error :o</h1>}>
        <MyBug />
      </ErrorBoundary>
      <ErrorBoundary render={(error) => <p>{error.toString()}</p>}>
        <MyBug />
      </ErrorBoundary>
    </div>
  )
}

ErrorBoundary va a ejecutar el prop render cuando haya un error y delega la lógica de renderizar a lo que nosotros decidamos colocar en esa función.

Con este cambio, nuestro componente está abierto a su extensión y cerrado a su modificación debido a que no necesitamos cambiar su código para extender el nuevo renderizado.

Incluso podemos ejecutar un componente en la función render como en el siguiente ejemplo:

const ErrorMessage = ({ error }) => {
  return <h1>{error.toString()}</h1>
}
export default function App() {
  return (
    <div className="App">
      <h1>Este es un componente destinado a crashear la app</h1>
      <ErrorBoundary render={(error) => <ErrorMessage error={error} />}>
        <MyBug />
      </ErrorBoundary>
      <ErrorBoundary render={(error) => <p>{error.toString()}</p>}>
        <MyBug />
      </ErrorBoundary>
    </div>
  )
}

Y con esto ya tenemos nuestro componente que incluso puedes usar en tus proyectos si así lo deseas.

Resumen del patrón Render Props

Aquí te dejo un resumen de los puntos clave que debes recordar sobre el patrón Render Props en React:

  • Un render prop es una función que un componente usa para saber qué renderizar.
  • Utiliza los render props cuando tengas un componente cuyo render va a ser dinámico o quieras reusar lógica entre componentes.
  • Las ventajas de usar render props son reusar código entre componentes y flexibilidad en los componentes.
  • Las desventajas de usar render props son que puede tender al callback hell en estructuras de componentes complejas.
  • Para implementar un render prop, debes pasar una función como prop al componente y ejecutarla en el render del componente.

Conclusión sobre render props

Has aprendido cómo identificar y aplicar esta técnica para respetar el principio de abierto - cerrado en tus proyectos ¡Bien por ti!

Un recurso interesante es este repositorio de github (https://github.com/jaredpalmer/awesome-react-render-props) que contiene un catálogo de ejemplos con render props y enlaces a más recursos recomendados.

En mi opinión, los render props usualmente van a ser mejor alternativa que HOC para reusar lógica entre componentes debido a su simpleza.


Si te ha gustado este análisis sobre el patrón Render Props, te invito a explorar los otros patrones avanzados en React JS que he analizado en la guía principal.

Y recuerda, si quieres llevar tus habilidades al siguiente nivel, no te pierdas el curso completo en el Canal de YouTube de Developero.