No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Next.js 2018

Curso de Next.js 2018

Roberto González

Roberto González

Intro a getInitialProps

6/23
Recursos

En esta clase vamos a ver la función getInitialProps de Next, que nos permite cargar el contenido principal de la página cuando tenemos que recurrir a una API.

Aportes 44

Preguntas 11

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Si están usando Next.js 9.3 o que sea más nuevo. En su documentación de getInitialProps() recomiendan usar getServerSideProps() o getStaticProps().

La principal diferencia entre ambas funciones es que getServerSideProps() se llama en cada carga de página, mientras que getStaticProps() solo es llamada al momento de hacer build. Con esto anterior ya claro, sabemos que debemos usar getServerSideProps() para hacer lo que el profesor hizo esta clase.

Mi codigo usando getServerSideProps() quedo de esta forma:

import 'isomorphic-fetch';

function App({ channels }) {
  return (
    <>
      <header>Podcasts</header>

      <div className="channels">
        {channels.map(channel => (
          <div className="channel">
            <img src={channel.urls.logo_image.original} alt="" />
            <h2>{channel.title}</h2>
          </div>
        ))}
      </div>

      <style jsx>{`
        header {
          color: #fff;
          background: #8756ca;
          padding: 15px;
          text-align: center;
        }

        .channels {
          display: grid;
          grid-gap: 15px;
          padding: 15px;
          grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
        }

        .channel {
          display: block;
          border-radius: 3px;
          box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
          margin-bottom: 0.5em;
        }

        .channel img {
          width: 100%;
        }

        .channel h2 {
          padding: 5px;
          font-size: 0.9em;
          font-weight: 600;
          margin: 0;
          text-align: center;
        }
      `}</style>

      <style jsx global>{`
        body {
          margin: 0;
          background: white;
          font-family: system-ui;
        }
      `}</style>
    </>
  );
}

export async function getServerSideProps() {
  let req = await fetch('https://api.audioboom.com/channels/recommended');
  let { body: channels } = await req.json();

  return { props: { channels: channels } };
}

export default App;

Si tienen alguna duda sobre el codigo me pueden preguntar o ir a la documentación de Next.js.

¿Alguien que me pueda decir porque me ocurre eso? Anexo codigo mas abajo

import "isomorphic-fetch";

export default class extends React.Component {
  static async getInitialProps() {
    let req = await fetch("https://api.audioboom.com/channels/recommended");
    let { body: channels } = await req.json();
    console.log({ channels });
    return { channels };
  }

  render() {
    const { channels } = this.props;
    return (
      <React.Fragment>
        <header>Podcast</header>

        {channels.map(channel => {
          <div>{channel.title}</div>;
        })}

        <style jsx>{`
          header {
            color: #fff;
            background: #8756ca;
            padding: 15px;
            text-align: center;
          }
        `}</style>

        <style jsx global>{`
          body {
            margin: 0;
            font-family: system-ui;
            background-color: white;
          }
        `}</style>
      </React.Fragment>
    );
  }
}

Tuve problemas siguiendo la clase, por las versiones de React y de Next, cambia la sintaxis.
Trate de hacer lo mismo con la nueva sintaxis en este sandbox por si le sirve a alguien. Codesandbox

Si están utilizando componentes funcionales, así podrían implementar el getInitialProps:

const Page = () => (
   <h1>Hello World</h1>
)

Page.getInitialProps = async () => {
}

export default Page

Este curso debería de actualizarse y dejar de usar componentes de clase

excelente curso muy bien explicado

Si están usando componentes funcionales y el getInitialProps les está dando dificultades pueden hacerlo de esta manera…

import { Fragment } from 'react'
import 'isomorphic-fetch'

function Home({ channels }) {
    return (
        <Fragment>
            <header>Podcast</header>

            {
                channels.map(channel => <div>{channel.title}</div>)
            }

            <style jsx>{`
                header {
                    color: #FFF;
                    background: #8756CA;
                    padding: 15px;
                    text-align: center;
                }
            `}</style>

            <style jsx global>{`
                body {
                    margin: 0;
                    font-family: system-ui;
                    background: white;
                }
            `}</style>
        </Fragment>
    )
}

Home.getInitialProps = async () => {
    const req = await fetch('https://api.audioboom.com/channels/recommended')
    const { body: channels } = await req.json()
    return { channels }
}

export default Home;

Código funcionando al día de hoy 05/OCT/19

import 'isomorphic-fetch';

export default class extends React.Component {
  static async getInitialProps() {
    let req = await fetch(
      'https://api.audioboom.com/channels/recommended?api_version=2'
    );

    let { body: channels } = await req.json();

    return { channels };
  }

  render() {
    const { channels } = this.props;
    return (
      <div>
        <header>Podcasts</header>

        <div className="channels">
          {channels.map(channel => (
            <div className="channel" key={channel.id}>
              <img src={channel.urls.logo_image.original} alt="" />
              <h2>{channel.title}</h2>
            </div>
          ))}
        </div>

        <style jsx>{`
          header {
            color: #fff;
            background: #8756ca;
            padding: 15px;
            text-align: center;
          }

          .channels {
            display: grid;
            grid-gap: 30px;
            padding: 20px;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
          }

          .channel {
            display: block;
            border-radius: 3px;
            box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
            margin-bottom: 0.5;
          }

          .channel img {
            width: 100%;
          }

          h2 {
            padding: 5px;
            font-size: 0.9em;
            font-weight: 600;
            margin: 0;
            text-align: center;
          }
        `}</style>

        <style jsx global>{`
          body {
            margin: 0;
            font-family: system-ui;
          }
        `}</style>
      </div>
    );
  }
}

Esta es otra forma de hacerlo con stales functional component y con unfetch

mis respetos al profesor y a esta clase. Es asombroso como con las tecnologías adecuadas y la experiencia adecuada en 14 minutos crea un catálogo de podcasts. Sin palabras.

Si alguien esta usando React Hooks se puede usar la function getInitialProps con esta syntaxis:

function Page({ stars }) {
  return <div>Next stars: {stars}</div>
}
Page.getInitialProps = async ({ req }) => {
  const res = await fetch('https://api.github.com/repos/zeit/next.js')
  const json = await res.json()
  return { stars: json.stargazers_count }
}
export default Page

Separe el código un poco para poder apreciar mejor lo que esta pasando.

Separe los estilos en un script llamado** component-style.js** lo curioso es que los estilos los toma correctamente pero no toma el :global(body) pero si lo coma cuando utilizo esto <style jsx global> y al usar un literal string use una variable para para el color .

const COLOR = "#1d76db";
export default (
    <style jsx>
        {`
            :global(body){
              padding: 0;
              margin: 0;
            }
            header {
              background-color: ${COLOR};
              color: white;
              padding: 15px;
              text-align: center;
            }
            .channels {
              display: grid;
              grid-gap: 15px;
              padding: 15px;
              grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
            }
            a.channel {
              display: block;
              margin-bottom: 0.5em;
              color: #333;
              text-decoration: none;
            }
            .channel img {
              border-radius: 3px;
              box-shadow: 0px 2px 6px rgba(0,0,0,0.15);
              width: 100%;
            }
            h2 {
              padding: 5px;
              font-size: 0.9em;
              font-weight: 600;
              margin: 0;
              text-align: center;
            }
        `}
    </style>
);

Este es el código del componente que estamos probando durante la clase, coloque algunos comentarios espero les funcionen de guia 😸.

import React, { Fragment } from "react";
import "isomorphic-fetch";

import StyleJSX from "./component-style";

const API = "https://api.audioboom.com/channels/recommended?api_version=2";

/**
 * Muestra el listado de PodCast.
 *
 * @param {object} props Listado de propiedades del componente.
 *
 * @return PodCastList.
 */
const PodCastList = (props) => {
    // Destructuración y definiendo un valor por defecto en el caos de que no exista el nodo
    const { channels = [] } = props;
    return (
        <Fragment>
            <header>Podcast List</header>
            <div className="channels">
                {
                    channels.map((channel) => {
                        const { id, title, urls: { logo_image: { original } } } = channel;
                        return (
                            <a className="channel" key={`potcast-${id}`}>
                                <img src={original} alt={title} />
                                <h2>{title}</h2>
                            </a>
                        );
                    })
                }
            </div>
            {StyleJSX}
        </Fragment>
    );
};

/**
 * Llamado a la api de audioboom.
 *
 * @return {Promise}.
 */
PodCastList.getInitialProps = async () => {
    const SEND = await fetch(API);
    // Destructuración y renombramiento del nodo body
    const { body: channels } = await SEND.json();
    return { channels };
};

export default PodCastList;

Según la documentación, getInitialProps dejó de ser recomendado, para este ejemplo utilicé getStaticProps en un componente funcional y se ve mucho más simple.

Notas sobre getInitialProps, hace data fetching en el compilado y tienes que regresar un objeto que tenga un elemento llamado props:

return {props:{channels}}
import fetch from 'node-fetch'
const index = ({ channels = [] }) => {
  return (
    <>
			...
    </>
  )
}

export async function getStaticProps() {
  const res = await fetch('https://api.audioboom.com/channels/recommended')
  const { body: channels } = await res.json()
  return { props: { channels } }
}

export default index
Los getInitialProps también funciona en el frontend o toca hacer otra función para pedir datos al api ?

si agrego la dependencia para porder importar css que venga de otro archivo, pierdo la versatilidad de que los estilos sean por componente y pasaran a ser globales?

Ejemplo de uso de fetch utilizando librería isomorphic-fetch

import fetch from 'isomorphic-fetch'

export default class extends React.Component {

    // getInitialProps() es una función que solo se puede ejecutar en Next.js 
    
    static async getInitialProps(){
        
        // Llamo al API de audioboom y obtengo la los caneles recomendados 
        let req = await fetch
        ('https://api.audioboom.com/channels/recommended')

        //  obtengo todo lo que contiene "body": [] y lo asigno a una variable llamada channels
        let { body: channels } = await req.json()

        // Regreso los todos los channels
        console.log(channels)
        return { channels }
    }

    render(){
        const { channels } = this.props
        return <div>
            <header>Podcasts</header>

            {
                channels.map((channel) => (
                    <div>{ channel.title } </div>

                ))
            }
            
            <style jsx>{`
            header {
                color: #fff;
                background: #8756ca;
                padding: 15px;
                text-align: center;
            }
           
            `}</style>

            <style jsx global>{`
            body {
                margin: 0;
                font-family: system-ui
                background: white;
            }
            `}</style>

        </div>
    }
}

Utilizar grid con Next.js

import fetch from 'isomorphic-fetch'

export default class extends React.Component {

    // getInitialProps() es una función que solo se puede ejecutar en Next.js 
    
    static async getInitialProps(){
        
        // Llamo al API de audioboom y obtengo la los caneles recomendados 
        let req = await fetch
        ('https://api.audioboom.com/channels/recommended')

        //  obtengo todo lo que contiene "body": [] y lo asigno a una variable llamada channels
        let { body: channels } = await req.json()

        // Regreso los todos los channels
        console.log(channels)
        return { channels }
    }

    render(){
        const { channels } = this.props

        return <div>
            <header>Podcasts</header>

            <div className="channels">
            {
                channels.map((channel) => (
                    <a className="channel">
                    <img src={ channel.urls.logo_image.original } alt="" />
                    <h2>{ channel.title }</h2>
                    </a>
                ))
            }
            </div>
            
            <style jsx>{`
            header {
                color: #fff;
                background: #8756ca;
                padding: 15px;
                text-align: center;
            }
            .channels {
                display: grid;
                grid-gap: 15px;
                padding: 15px;
                grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
            }
            .channel {
                display: block;
                border-radius: 3px;
                margin-bottom: 0.5em;
                color: #333;
                text-decoration: none;
            }
            .channel img {
                width: 100%;
                border-radius: 3px;
                box-shadow: 0px 2px 6px rgba(0,0,0,0,.15);
                width: 100px;
            }
            h2 {
                padding: 5px;
                font-size: 0.9em;
                font-weight: 600;
                maring: 0;
                text-align: center;
            }
           
            `}</style>

            <style jsx global>{`
            body {
                margin: 0;
                font-family: system-ui
                background: white;
            }
            `}</style>

        </div>
    }
}

getInitialProps - solo funciona en Next.js - NO funciona en otro framework

Los estilos usados en clase:

<style jsx>{`
           header {
               color:#fff;
               background:#8756ca;
               padding:15px;
               text-align:center;
           }
           .channels {
               display: grid;
               grid-gap: 15px;
               padding: 15px;
               grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
           }
           .channel {
               display: block;
               border-radius: 3px;
               box-shadow: 0 2px 6px rgba(0,0,0,0.15);
               margin-bottom: 0.5em;
           }
           .channel img {
               width:100%;
           }
           h2{
            padding: 5px;
            font-size: 0.9em;
            font-weight: 600;
            margin: 0;
            text-align:center;
           }

        `}
        </style>
        <style jsx global>{`
        body{
            margin:0;
            font-family:system-ui;
            background:white;
        }
        `}
        </style>

Si en algún momento aparece el warning de incluir el api version, la forma de llamarla es: https://api.audioboom.com/channels/recommended?api_version=2

Buenas, aca no me esta funcionando los Css.
Alguna idea???

const renderChannel = channel => (
  <a className="channel" key={channel.id}>
    <img src={channel.urls.logo_image.original} alt="" />
    <h2>{channel.title}</h2>
  </a>
);

const renderChannels = ({ channels }) => (
  <div className="channels">
    {channels.map(channel => renderChannel(channel))}
  </div>
);

const Page = props => (
  <div>
    <header>Podcasts</header>
    {renderChannels(props)}
    <style jsx>{`
      header {
        color: #fff;
        background: #8756ca;
        padding: 15px;
        text-align: center;
      }
      .channels {
        display: grid;
        grid-gap: 15px;
        padding: 15px;
        grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
      }
      a.channel {
        display: block;
        margin-bottom: 0.5em;
        color: #333;
        text-decoration: none;
      }
      .channel img {
        border-radius: 3px;
        box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
        width: 100%;
      }
      h2 {
        padding: 5px;
        font-size: 0.9em;
        font-weight: 600;
        margin: 0;
        text-align: center;
      }
    `}</style>

    <style jsx global>
      {`
        body {
          background: white;
          font-family: system-ui;
          margin: 0;
        }
      `}
    </style>
  </div>
);

[NextJS] Traer los datos desde un API

Acabo de buildear la aplicacion y arrancarla usando el prefetch en los links pero igual no me precarga mi archivo de channel.js en network como aparece en el video, ¿Por que?

import "isomorphic-fetch";
import Link from "next/link";

export default class extends React.Component {
  static async getInitialProps() {
    let request = await fetch("https://api.audioboom.com/channels/recommended");
    let { body: channels } = await request.json();

    return { channels };
  }

  render() {
    const { channels } = this.props;
    return (
      <React.Fragment>
        <header className="Head">Podcast</header>
        <div className="grid-container">
          {channels.map(channel => (
            <section className="container">
              <header>
                <Link href={`/channel?id=${channel.id}`} prefetch>
                  <a className="link">
                    <h1 className="title" key={channel.id}>
                      {channel.title}{" "}
                    </h1>
                  </a>
                </Link>
              </header>
              <Link href={`/channel?id=${channel.id}`} prefetch>
                <a className="link">
                  <nav>
                    <img
                      className="logoImg"
                      src={channel.urls.logo_image.original}
                    />
                  </nav>
                </a>
              </Link>
              <main>
                <h2 className="description">{channel.description}</h2>
              </main>
            </section>
          ))}
        </div>```

Alguien sabe que theme de vscode esta usando?

<style jsx>{
header{
color: #fff;
background: #8756ca;
padding: 15px
}
} </style> <style jsx global>{
body{
margin: 0;
font-family: system-ui;
background:white
}
} </style>

Les comparto otra api libre para jugar: https://randomuser.me

Para quienes no les pinte bien las respuests esta fue mi solucion ya que map no me lo estaba retornando:

      <div>
        { channels.map((channel) => {
          return (<div className="channels">
            <img src={ channel.urls.logo_image.original } alt="" />
            <h2>{ channel.title }</h2>
          </div>)
        }) }
      </div>

Saludos

te faltó ponerle un key

Creo que una mejor práctica sería instalar fetch como una dependecnia del desarrollo, osea npm install --save-dev isomorphic-unfetch

Esto generara un objeto llamado devDependencies
"devDependencies": {
“isomorphic-unfetch”: “^3.0.0”
}

Lo adecuado es usar unfetch cuando se trata de next js

Brutal CSS Grid Layout

Hola mi gente, pregunta en el getInitialProps hace el get a la API para obtener los datos pero como puedo hacer un post, put o delete? tambien existe alguna funcion en la que se recomiende?

Me voló la cabeza eso de grid css! _

vengan pero tengo una pregunta, los datos del api se descargan del lado del servidor y se “fusionan” y terminan dentro del bundly?

Next tiene un gran parecido a React Native, la forma en que recibe los props, en como se consume las API y la forma de agregar estilos es de una manera muy intuitiva y agil! Genial!!

Isomorphic-fecth sirve para dar soporte a al servidor para utilizar fetch

Buenisima clase!

¿Alguien entendió las restricciones de getInitialProps?

¿Cómo puedo usar el <style jsx> como si fuera css?

Me explico, a mi me toma el css como si fuera un texto plano, por lo cual no puedo ver los colores, no me autocompleta y debo escribir todo a mano. ¿Cómo puedo hacer para que me funciona como si fuera un archivo .css?

import 'isomorphic-fetch'
export default class extends React.Component{
    static async getInitialProps(){
        let req =  await fetch
        ('https://api.audioboom.com/channels/recommended')
        let {body: channels } = await req.json()
  
        return{channels}
    }
    
    
    render(){
        const {channels} = this.props

        return <React.Fragment>

            <header> PODCASTS</header>

            <div  clasName="channels">

            {channels.map((channel) => (

                <div className="channel">

                    <img src={channel.urls.logo_image.original} alt="Logo del podcast"/>

                    <h2>{channel.title}</h2>

                </div>
                
            )
            )}

            </div>

            
        
    <style jsx>{`
    header{
        color: #fff;
        background:purple;
        padding: 15px;
    }
    .channels{
        display: grid;
        grid-gap: 15px;
        padding: 15px;
        grid-template-columns:repeat(auto-fill,minmax(160px, 1fr));
    }

    .channel{
        display:block;
        border-radius:3px;
        box-shadow: 0px 2px 6px rgba (0,0,0,0.15)
        margin-buttom:0.5em;
    }
    .channel img{
        width:100%;
    }
    h2{
        padding:5px;
        fontsize:0.9em;
        font-weignt:600;
        margin:0;
        text-align:center;

    }
    `}</style>

<style jsx global> {`
 body{
     margin:0;
     font-family: system-ui;
    background:white;
    text-align:center;

`}</style>


         </React.Fragment>
    }
}```




No me esta funcionando el ccs grid y no se cual pueda ser la causa si alguien pueda ayudarme lo agradeceria

Para las personas que tuvieron problemas con el css y sobre todo con <style jsx global> así fue como lo corregi.

<style jsx>{`

        :global(body) {
          padding: 0;
          margin: 0;
          font-family: system-ui;
        }
        header {
          color: #fff;
          background: #8756ca;
          padding: 15px;
          text-align:center;
        }
      `}</style>

Alguien sabe si se puede cambiar o modificar la pagina de error 404 de next js…?

Los estilos!

        <style jsx>{`
          :global(body) {
            margin: 0;
            font-family: system-ui;
            background: white;
          }
          header {
            color: #fff;
            background: #8756ca;
            padding: 15px;
            text-align: center;
          }
          .channels {
            display: grid;
            grid-gap: 15px;
            padding: 15px;
            grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
          }
          a.channel {
            display: block;
            margin-bottom: 0.5em;
            color: #333;
            text-decoration: none;
          }
          .channel img {
            border-radius: 3px;
            box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
            width: 100%;
          }
          h2 {
            padding: 5px;
            font-size: 0.9em;
            font-weight: 600;
            margin: 0;
            text-align: center;
          }
        `}</style>

Estaba viendo los comentarios y varios hablan sobre los compinenetes funcionales. Es una mejor forma de escritura de los componentes?