Hasta antes de la versión 16, solo había una forma -nativa- de compartir propiedades entre componentes y era por medio de Prop drilling o, dicho en español, taladramiento ,que quiere decir, que las propiedades fluyen de arriba hacia abajo en una jerarquía previamente establecida.
Prop Drilling y Redux
Era común tener componentes como el siguiente:
class Me extends React.Component<P, S> {
state = {
lastName = 'Garzaki'
}
render = _ => (
<div>
<p>Hola, yo soy Gustavo {this.state.lastName} y mi niña se llama </p>
<Child lastName={this.state.lastName} />
</div>
)
}
class Child extends React.Component<P, S> {
render = _ => (
<p>Mía {this.props.lastName}</p>
)
}
A esto se le llama prop drilling que no es más que pasar las propiedades de padre a hijo, de hijo a nieto, de nieto a bisnieto y así sucesivamente. Con el pasar del tiempo llegaron nuevas librerías complementarias para React, como Redux, Mobx, entre otras, que lo que ofrecen es un manejo de estados intercomponentes, el cual es global, de manera que no es necesario taladrar toda la jerarquía de componentes para pasar propiedades desde el componente A
hasta el F
dentro de la jerarquía, si no que solo necesitas subscribirte al estado o a una parte de él para estar escuchando por cambios en las propiedades que forman parte de esa porción del estado. Además de esto, nos proveen una manera realmente sencilla de compartir propiedades entre hermanos.
Sin embargo, esto trajo consigo una consecuencia inminente e inevitable: complejidad. Necesitábamos tener en cuenta los middlewares, las acciones, configurar el store, entre otros, lo que hacía y hace aún a Redux bastante complejo de implementar.
Context API - ¿Alternativa a Redux? 🤔
A partir de React 16, se implementó una nueva herramienta conocida como Context API. Esta nueva herramienta se creó como propuesta al prop drilling y a Redux. La idea detrás de Context API es la misma que Redux, pero de manera mucho más ligera, concisa y lo mejor de todo, oficial.
Esta nueva característica funciona creando un contexto, que es un entorno en tiempo de ejecución que guarda ciertos datos, como variables, funciones, entre otras. Este contexto se divide en dos: Provider
y Consumer
.
Para crear un contexto, basta con usar el método React.createContext
:
const AppContext = React.createContext({})
export const AppProvider = AppContext.Provider
export const AppConsumer = AppContext.Consumer
El Provider es donde se almacena la información que se quiere consumir; esta información se pasa por un atributo llamado value
. Piensa en esto como si fuese una API a la cual vamos a consumir.
Por otro lado, el Consumer es el elemento que se encarga de consumir los datos que contiene el Provider, de manera que actúa como un proxy para nuestros componentes.
import { AppProvider, AppConsumer } from './context'
class App extends Component<P, S> {
state = {
title: 'Hello from App',
updateTitle: title => {
this.setState({ title })
}
}
render = _ => (
<AppProvider value={this.state}>
<Header />
{this.props.children}
</AppProvider>
)
}
export default App
Una vez que el Provider
ya tiene un valor, se puede consumir sin importar la profundidad en donde se encuentre el componente que desea consumir la información:
const Header = _ => (
<header className="header">
<Title />
</header>
)
const Title = _ => (
<AppConsumer>
{
context => (
<h1 className="header__title">
{ context.title }
</h1>
)
}
)
Como vemos, a pesar que el componente Title
no es hijo directo de App
, podemos hacer uso de su estado sin heredarlo como propiedad, aún si Title
estuviese a muchos niveles más de profundidad.
No solo eso, también podemos actualizar el valor del Provider
actualizando el estado del componente que lo provee. Las posibilidades son muchas y depende de ti como desarrollador decidir el uso que le quieres dar.
Conclusiones
Context API es una alternativa bastante buena a Redux. Si lo que buscas es algo simple y funcional, es la opción para ti. Sin embargo, pueden existir ocasiones en que no sea lo suficientemente útil para ti y quieras usar Redux y otra alternativa. En lo personal, me basta con Context API e incluso para crear mi propio Redux basada en ella como React Waterfall.
Top comments (5)
Hi Gustavo,
my Spanish is not good :) sorry for that.
I would like to get your opinion on github.com/iusehooks/redhooks which uses the Context API and the Hooks.
Thanks!
Hi Antonio, redhooks looks pretty good. It's very similar to Redux in fact. I'll try it and make some tutorial about it ;)
Thanks for the link!
it depends only on react hooks and context api. You do not need react-redux to use it, middleware are supported and it is really a tiny library. Thanks for your feedback
Hola Gus, muy buena explicación. Justo estoy presentando complejidad con props y esto parece la solución. Saludos y gracias.
Hi there! Gracias! Esto lo puedes aprovechar mejor con el hook
useContext
! Ya cocinaré algo al respecto. 🤙