Que es un contexto en React
Tags: javascript, react
Published: 2022-05-21 23:24:43

Cuando desarrollamos aplicaciones web basada en componentes, tenemos la necesidad de compartir información o funcionalidad a diferentes componentes en diferentes niveles de profundidad.

Si bien las propiedades en React nos ofrecen la posibilidad de resolver esta problema, esta solución pierde sentido (abierto a interpretaciones) entre mas niveles de profundidad de requiera recorrer.

Por ello React ofrece dos funciones para dar solución a este problema `createContext` y `useContext`.

## Problema
Tenemos una aplicación que renderiza una lista de usuarios y un buscador, el cual hace una búsqueda con base en el nombre de los usuarios.

Una forma de llevar a cabo esta aplicación es teniendo un estado para el valor del campo de búsqueda y utilizar este estado para hacer el filtrado en el array de usuarios.

La estructura de la aplicación esta de la siguiente manera:

```
src/
├── components/
│   ├── field/
│   │   ├── index.jsx
│   │   └── field.module.css
│   ├── searcher/
│   │   ├── index.jsx
│   │   └── searcher.module.css
│   └── user/
│       ├── index.jsx
│       └── user.module.css
├── styles
├── app.jsx
└── main.jsx
```

Y la composicion de componentes es la siguiente

```jsx
// app.jsx
<main>
  <Searcher />
</main>

// searcher.jsx
<section>
  <Field />
</section>

// field.jsx
<input />
```

Empecemos definiendo nuestro contexto, en este caso `SearchContext`.

```
import { createContext } from 'react';

export const SearchContext = createContext();
```

Ahora debemos hallar la forma en que el componente `Field` pueda consumir el estado `searchValue` y la función `onChangeSearch`.

Para ello, utilizaremos `useContext` en `Field` de la siguiente manera:

```jsx
import { useContext } from 'react';
import { SearchContext } from '~/contexts/search-context';
import styles from './field.module.css';

const Field = () => {
  const { searchValue, onChangeSearch } = useContext(SearchContext);

  return (
    <input
      type="text"
      value={searchValue}
      onChange={onChangeSearch}
      placeholder="Buscar por nombre"
      className={styles.field}
    />
  );
};

export default Field;

```
Como vemos es importante pasarle como parámetro el contexto que queremos consumir a `useContext`.

En este punto, aun no sabemos donde están definidos `searchValue` y `onChangeSearch`. 

En este caso, lo propio es definir este objeto en `app.jsx` ya que es el componente donde se están definiendo el estado y el método que nos interesan.

Ahora para poder definir y compartir este objeto, debemos hacerlo a través de un proveedor, este proveedor se encuentra en nuestro objeto contexto que nos devolvió `createContext` y se utiliza de la siguiente manera:

```jsx
<SearchContext.Provider value={{ value: search, onChangeSearch }}>
  <Searcher />
</SearchContext.Provider>
```

Como vemos nuestro proveedor tiene una propiedad llamada `value` la cual contiene el valor que el contexto compartirá.

El proveedor esta envolviendo al componente que queremos compartir dicha información.

De esta manera hemos logrado que `Field` altere el estado y se haga el filtrado de los usuarios.

Les dejo el código final.

[demo](https://stackblitz.com/edit/vitejs-vite-ehc4xq?embed=1&file=src/App.jsx&hideExplorer=1)