DEV Community

Cover image for Next JS React con Context API
Edison Sanchez
Edison Sanchez

Posted on

Next JS React con Context API

Uno de mis grandes temores en iniciar con Next.JS y SSR era el hecho de no poder contar con las herramientas CRA (Create React App) me permitia, además de la flexibilidad de la misma.

Una de las herramientas más comúnmente empleada en mis proyectos es Context API; a mi parecer me entrega las herramientas necesarias de una manera facil para poder manejar el estado de los componentes y su representación global en la aplicación.

Para iniciar, usando create-react-next creamos una aplicación con Next y React. A continuación una definición de cómo uso Context API mediante useContext:

Context.js

import React, { useContext, createContext } from 'react';

//Context
export const AppContext = createContext(null);

//Provider
export const AppContextProvider = ({ children }) => {
  const [variableState, setVariableState] = React.useState(false);

  //ComponentDidMouunt
  React.useEffect(() => {

  }, []);

  //
  const values = React.useMemo(() => (
    { variableState,      // States que seran visibles en el contexto.
      setVariableState,   // Funciones que son exportadas para manejo externo.
    }), 
    [ 
      variableState ]);   // States que serán visibles en el contexto.

  // Interface donde será expuesto como proveedor y envolverá la App.
  return <AppContext.Provider value={values}>{children}</AppContext.Provider>;
}

//
export function useAppContext() {
  const context = useContext(AppContext);

  if(!context){
    console.error('Error deploying App Context!!!');
  }

  return context;
}

export default useAppContext;
Enter fullscreen mode Exit fullscreen mode

Mediante el useContext exportamos el Consumer que puede usarlo en cualquier componente, pagina, o función dentro del proyecto.

home.js

import Head from 'next/head'
import { useEffect } from 'react'
import { useAppContext } from '../contexts/AppContext';

export const Home = () => {
  const { variableState, setVariableState } = useAppContext();


  //ComponentDidMouunt
  useEffect(() => {
    setVariableState(true);
   }, [variableState] );


  return (
    <div className="container">
      <Head>
        <title>Testing Next.JS with Context and Hooks</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1 className="title">
          CONTEXT APP {`${variableState}`}
        </h1>

        <p className="description">
          Get Started with AppContext API, using ContextAPI.
        </p>
      </main>

      <style jsx>{`
        .container {
          min-height: 100vh;
          padding: 0 0.5rem;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
        }

        main {
          padding: 5rem 0;
          flex: 1;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
        }


        .title a {
          color: #0070f3;
          text-decoration: none;
        }

        .title a:hover,
        .title a:focus,
        .title a:active {
          text-decoration: underline;
        }

        .title {
          margin: 0;
          line-height: 1.15;
          font-size: 4rem;
        }

        .title,
        .description {
          text-align: center;
        }

        @media (max-width: 600px) {
          .grid {
            width: 100%;
            flex-direction: column;
          }
        }
      `}</style>

      <style jsx global>{`
        html,
        body {
          padding: 0;
          margin: 0;
          font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
            Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue,
            sans-serif;
        }

        * {
          box-sizing: border-box;
        }
      `}</style>
    </div>
  )
}

export default Home;
Enter fullscreen mode Exit fullscreen mode

Es lo mismo que haría en CRA, pero al ejecutarlo:

TypeError: Cannot destructure property `variableState` of 'undefined' or 'null'.
Enter fullscreen mode Exit fullscreen mode

Bueno, entonces dónde se configura el , donde esta , o para envolver mi aplicación. Esta parte es un poco "tricky", se trata de hacer una especie de "Overload" de App. Para lo cual creamos un archivo _app.js en la carpeta Pages.

pages/_app.js
Enter fullscreen mode Exit fullscreen mode

Este debe suplantar la entrada de la aplicación, permitiendo envolver el o los proveedores de contextos que se requieran así como todas las funcionalidades o herramientas que requieran esta modalidad de provider.

_app.js

import App, { Container } from 'next/app';
import { AppContextProvider } from "../contexts/AppContext";

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;
    return (
      <AppContextProvider>
        <Component {...pageProps} />
      </AppContextProvider>
    );
  }
}

export default MyApp;
Enter fullscreen mode Exit fullscreen mode

Se importa el contexto, y después de este corto procedimiento, ya estamos totalmente funcionales.

Ver Demo

Oldest comments (3)

Collapse
 
rossangus profile image
Ross Angus

I've spent the past two days trying to get the Context API working with Next and this is the only article I've read which works, has all of the code required, and uses functional components (rather than class based). Thank you, Edison!

Collapse
 
jerezrd profile image
Justin Jerez

Aún no lo he probado, pero es una grata sorpresa ver personas desde mi país contribuyendo a la comunidad. Muchas gracias y saludos desde República Dominicana!!

Collapse
 
sdann26 profile image
Danilo Blas

Me sirvio muchisimo ya que siempre que pasaba entre pages se actualizaba el context que tenía puesto en el Layout y al final usando esto todo funciono de manera correcta!

Gracias :D