4Geeks logo
Sobre Nosotros

Catálogo de contenidos

Para los geeks autodidactas, este es nuestro extenso catálogo de contenido con todos los materiales y tutoriales que hemos desarrollado hasta el día de hoy.

Tiene sentido comenzar a aprender leyendo y viendo videos sobre los fundamentos y cómo funcionan las cosas.

Data Science and Machine Learning - 16 wks

Full-Stack Software Developer - 16w

Buscar en lecciones

Aprendizaje social y en vivo

La forma más eficiente de aprender: Únete a una cohorte con compañeros, transmisiones en vivo, sesiones improvisadas de codificación, tutorías en vivo con expertos reales y mantenga la motivación.

← Regresar a lecciones
Editar en Github

Implementando un estado global con context API

¿Cómo funciona la API de contexto?

Por qué la vida antes de la API de contexto era más difícil

La gente dice que React.js hace que las cosas fáciles sean difíciles y que las difíciles sean fáciles. Me encanta ese dicho, es tan cierto 😓. Algunos ejemplos de ello:

  1. ¿Por qué es tan difícil compartir algunos datos en toda la aplicación?

  2. ¿Por qué es tan difícil pasar datos entre componentes? También conocidas props. Las props o propiedades se usan cuando quieres pasar datos entre un padre y un hijo ¿Pero qué pasa si tenemos que ir más lejos? Es un infierno.

  3. ¿¿Redux (https://redux.js.org/)?? Es demasiado.

La context API está aquí para resolver algunos de esos enigmas:

  1. Tener una aplicación global centralizada: en lugar de limitarte a los estados locales en las vistas, ahora puede compartir datos en un componente principal y sus componentes relativos ( hijos, nietos y así). El estado centralizado se llama store y podemos extenderlo/propagarlo utilizando el Context.Provider y el Context.Consumer

  2. Propagación y re-renderizado de datos: cuando este estado centralizado llamado estado global (store) cambia, desencadena una re-renderización de todos los componentes hijos (tu aplicación completa) lo que genera nuevos datos para mostrar en la UI. Un setState pero central.

  3. Si ya has trabajado con react, probablemente hayas sentido la frustración de pasar propiedades en toda tu aplicación, nosotros lo llamamos el "infierno de propiedades".

¿Cómo funciona la API de contexto?

El concepto detrás es muy simple: hay un solo y gran proveedor que provee información para muchos consumidores, no hay límites en la cantidad de consumidores.

Cada vez que los datos del proveedor cambian, todos los consumidores reciben una notificación. Es muy similar a cómo funcionan la señal de la TV. Un canal de TV emite una señal de datos y todas las antenas de TV consumen esa señal, reciben el nuevo contenido y renderizan la imagen en los televisores.

Todo el mundo tiene acceso al contexto global ahora.

Explicación Context API

Flujo de datos unidireccional

El store es ahora la pieza más delicada de información de nuestra aplicación, y es muy suceptible a malos usos, es decir, un cambio malo y toda la aplicación se vendrá abajo. Para evitar este posible escenario debemos asegurarnos que la información de nuestro store sea read-only para los consumidores, y que solo pueda actualizarse nuevamente con un conjunto limitado de funciones. Como un state normal, no cambiamos el state, establecemos uno nuevo. Este paradigma arquitectónico se llama Flux.

Flux

Profundizando en la arquitectura de Flux

Debemos separar el store de las actions y las views (componentes) y asegurarnos de que todas las views o vistas llaman a acciones para actualizar el store. Nunca cambiaremos el store directamente desde una vista. Estoy siendo redudante, lo sé... lo hago a propósito...

Ahora todo junto

  • Vamos a implementar un solo punto de verdad en toda la aplicación: el global state.
  • Este estado contendrá la información y las funciones para establecer un nuevo state: store y actions .
  • Vamos a propagarlo en toda nuestra aplicación utilizando el contexto: Context.Provider y Context.Consumer (si usa clases como componentes de React) o hook useContext() (si usa funciones como componentes de React)

Una implementación sencilla

De acuerdo, después de un par de horas para hacer la implementación de la API de contexto más simple sin usar enlaces... ¡esto es lo que obtuve en 5 pasos simples!:

  • Paso 1 (Crear el contexto): Este paso casi no tiene lógica, simplemente llama a la función createContext desde React. Ese objeto se compartirá con todos los consumidores durante el tiempo de vida de la aplicación, contendrá la aplicación del store y actions.

AppContext.js

1// Paso 1: define un contexto que se compartirá dentro de toda la aplicación. 2 3import React from 'react'; 4 5const AppContext = React.createContext(null); 6
  • Paso 2 (Store y actions): Crea un componente ContextWrapper que utilizaremos para pasarle el context (paso 1) a los consumidores. En el estado del ContextWrapper declaramos nuestro global state inicial, que incluye la información/store store y las funciones actions.

Nota: Debemos importar tanto el AppContext cómo él ContextWrapper.

1// Paso 2: Crea un componente ContextWrapper que debe ser el padre de cada consumidor. 2 3import React from 'react'; 4 5export const AppContext = React.createContext(null); 6 7export const ContextWrapper = (props) => { 8 const [ store, setStore ] = useState({ 9 todos: ["Make the bed", "Take out the trash"] 10 }); 11 const [ actions, setActions ] = useState({ 12 addTask: title => setStore({ ...store, todos: store.todos.concat(title) }) 13 }); 14 15 return ( 16 <AppContext.Provider value={{ store, actions }}> 17 {props.children} 18 </AppContext.Provider> 19 ); 20}
  • Paso 3 (Vistas): Ahora podemos contener al componente principal dentro del ContextWrapper para que todos sus componentes hijos tengan accceso al Context.Consumer. En este breve ejemplo usaremos el componente <TodoList /> como componente principal (la declaración está en el último paso).

index.js

1// Step 3: Ubica tu comoponente principal dentro del contenedor ContextWrapper, 2 3import React from 'react'; 4 5import { ContextWrapper } from 'path/to/AppContext.js'; 6 7const MyView = () => ( 8 <ContextWrapper> 9 <TodoList /> 10 </ContextWrapper> 11 ); 12 13ReactDOM.render(<MyView />, document.querySelector("#app")); 14
  • Paso 4: Ahora podemos crear el componente TodoList sabiendo que podemos usar el Context.Consumer para leer el store desde el global state (no se necesitan props). En este caso el componente renderizará los to-dos y también podrá añadir nuevas tareas a lista.
1// Step 4: Add the Context.Consumer tag to any component 2 3import React, { useContext } from 'react'; 4import { AppContext } from 'path/to/AppContext.js'; 5 6export const TodoList = () => { 7 const context = useContext(AppContext) 8 return <div> 9 {context.store.todos.map((task, i) => (<li>{task}</li>))} 10 <button onClick={() => context.actions.addTask("I am the task " + context.todos.length)}> + add </button> 11 </div> 12}

En su variante desestructurada. Presta atención a cómo eso también simplifica la forma en que accedemos al store:

1 const {store, actions} = useContext(AppContext); 2 return <div> 3 {store.todos.map((task, i) => (<li>{task}</li>))} 4 <button onClick={() => actions.addTask("I am the task " + context.todos.length)}> + add </button> 5 </div>

Prueba el código en vivo