Nouveau : Datasets open source gratuits disponibles !Decouvrir →
Intermediaire 30 min Next.js

Debuter avec Next.js

Pourquoi Next.js ?

Contexte réal : Un dev a besoin de Next.js pour construire des applications web modernes et performantes, qui offrent une expérience utilisateur fluide et rapide.

Un cas d'usage concret : Vous développez un site e-commerce avec des pages dynamiques comme les produits individuels et la panier d'achat. Avec Next.js, vous pouvez générer les pages statiques pour chaque produit au moment de sa publication et mettre à jour en temps réel lorsque le stock change.

Prerequis

  • Connaissances nécessaires :

    • JavaScript ES6+
    • HTML/CSS
    • Connaissance des concepts de React (state, props, hooks)
  • Outils à installer :

    • Node.js v14.0.0 ou supérieure
    • npm v6.0.0 ou supérieure

Concepts fondamentaux

1. Pages et Routes

Définition : Next.js utilise les fichiers de pages pour définir les routes de l'application.

## pages/index.js
export default function Home() {
  return <h1>Bienvenue sur mon site</h1>;
}

2. Routing dynamique

Définition : Permet d'afficher des pages selon un modèle.

## pages/posts/[id].js
import { useRouter } from 'next/router';

export default function Post() {
  const router = useRouter();
  const { id } = router.query;

  return <h1>Post #{id}</h1>;
}

3. API Routes

Définition : Permet de créer des routes côté serveur pour traiter les requêtes HTTP.

## pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ name: 'John Doe' });
}

4. Styles et CSS Modules

Définition : Permet de gérer les styles avec des fichiers .css ou .module.css.

## components/Button.module.css
.button {
  padding: 10px 20px;
  background-color: #6200ea;
  color: white;
  border-radius: 5px;
}

## components/Button.js
import styles from './Button.module.css';

export default function Button({ children }) {
  return <button className={styles.button}>{children}</button>;
}

5. State Management

Définition : Utilisez le useState hook pour gérer l'état local des composants.

## pages/index.js
import { useState } from 'react';

export default function Home() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Compteur : {count}</p>
      <button onClick={() => setCount(count + 1)}>Incrementer</button>
    </div>
  );
}

6. Props

Définition : Permet de passer des données entre les composants.

## components/Hello.js
export default function Hello({ name }) {
  return <h1>Bonjour {name}</h1>;
}

## pages/index.js
import Hello from '../components/Hello';

export default function Home() {
  return (
    <div>
      <Hello name="John" />
    </div>
  );
}

7. Hooks personnalisés

Définition : Permet de créer des fonctions réutilisables avec le hook useEffect.

## hooks/useFetch.js
import { useState, useEffect } from 'react';

export default function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchData() {
      const response = await fetch(url);
      const result = await response.json();
      setData(result);
      setLoading(false);
    }

    fetchData();
  }, [url]);

  return { data, loading };
}

## pages/posts/[id].js
import useFetch from '../hooks/useFetch';

export default function Post() {
  const { id } = useRouter();
  const { data, loading } = useFetch(`https://jsonplaceholder.typicode.com/posts/${id}`);

  if (loading) return <div>Chargement...</div>;

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </div>
  );
}

8. Static Generation

Définition : Permet de générer des pages statiques au build.

## pages/posts/[id].js
export async function getStaticPaths() {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  const posts = await response.json();

  return {
    paths: posts.map(post => ({ params: { id: post.id.toString() } })),
    fallback: false,
  };
}

export default function Post({ post }) {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

export async function getStaticProps({ params }) {
  const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
  const post = await response.json();

  return { props: { post } };
}

Mise en pratique : Projet fil rouge

Projet : Gestionnaire de tâches

  1. Initialisation du projet

    npx create-next-app@latest task-manager
    cd task-manager
    
  2. Création d'une page d'accueil

    # pages/index.js
    export default function Home() {
      return (
        <div>
          <h1>Task Manager</h1>
          <ul>
            <li><Link href="/tasks">Tâches</Link></li>
            <li><Link href="/add-task">Ajouter une tâche</Link></li>
          </ul>
        </div>
      );
    }
    
  3. Création de la page des tâches

    # pages/tasks.js
    import { useState } from 'react';
    import Link from 'next/link';
    
    export default function Tasks() {
      const [tasks, setTasks] = useState([]);
    
      const fetchTasks = async () => {
        const response = await fetch('https://jsonplaceholder.typicode.com/todos');
        const data = await response.json();
        setTasks(data);
      };
    
      useEffect(() => {
        fetchTasks();
      }, []);
    
      return (
        <div>
          <h1>Tâches</h1>
          <ul>
            {tasks.map(task => (
              <li key={task.id}>
                <Link href={`/tasks/${task.id}`}>{task.title}</Link>
              </li>
            ))}
          </ul>
        </div>
      );
    }
    
  4. Création de la page d'une tâche

    # pages/tasks/[id].js
    import { useRouter } from 'next/router';
    
    export default function Task() {
      const router = useRouter();
      const { id } = router.query;
    
      // Simuler une récupération de données à partir d'un API
      const task = {
        id,
        title: `Tâche ${id}`,
        description: `Description de la tâche ${id}`
      };
    
      return (
        <div>
          <h1>{task.title}</h1>
          <p>{task.description}</p>
        </div>
      );
    }
    
  5. Création de la page pour ajouter une tâche

    # pages/add-task.js
    import { useState } from 'react';
    import Link from 'next/link';
    
    export default function AddTask() {
      const [title, setTitle] = useState('');
      const [description, setDescription] = useState('');
    
      const handleSubmit = async (e) => {
        e.preventDefault();
        // Simuler l'ajout de la tâche à un API
        console.log('Tâche ajoutée :', { title, description });
        setTitle('');
        setDescription('');
      };
    
      return (
        <div>
          <h1>Ajouter une tâche</h1>
          <form onSubmit={handleSubmit}>
            <input
              type="text"
              placeholder="Titre"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
            />
            <textarea
              placeholder="Description"
              value={description}
              onChange={(e) => setDescription(e.target.value)}
            />
            <button type="submit">Ajouter</button>
          </form>
          <Link href="/">Retourner à la liste des tâches</Link>
        </div>
      );
    }
    

Erreurs fréquentes et debugging

1. Error: Element type is invalid

Code incorrect :

const MyComponent = (props) => {
  return <h1>{props.title}</h1>;
};

export default MyComponent;

Code correct :

import React from 'react';

const MyComponent = ({ title }) => {
  return <h1>{title}</h1>;
};

export default MyComponent;

2. Error: Function components cannot be given keys as children

Code incorrect :

return (
  <ul>
    {tasks.map(task => (
      <li key={task.id}>
        <Task task={task} />
      </li>
    ))}
  </ul>
);

Code correct :

return (
  <ul>
    {tasks.map(task => (
      <li key={task.id}>
        <Task {...task} />
      </li>
    ))}
  </ul>
);

3. Error: Can't perform a React state update on an unmounted component

Code incorrect :

useEffect(() => {
  const interval = setInterval(() => {
    setData(data + 1);
  }, 1000);

  return () => clearInterval(interval);
}, []);

Code correct :

const [data, setData] = useState(0);

useEffect(() => {
  let mounted = true;

  const interval = setInterval(() => {
    if (mounted) {
      setData(data + 1);
    }
  }, 1000);

  return () => {
    mounted = false;
    clearInterval(interval);
  };
}, []);

Pour aller plus loin

  1. Gestion des formulaires :

  2. Optimisation des performances :

  3. Intégration avec des bases de données :

    • Utiliser next-connect pour créer une API REST côté serveur et intégrer les données dans les pages Next.js. GitHub next-connect

Défi pratique :

Créez un mini-projet d'une application de to-do list complète avec des fonctionnalités suivantes :

  • Ajouter une tâche
  • Supprimer une tâche
  • Marquer une tâche comme terminée

Utilisez les concepts appris, notamment la gestion du state et les API Routes.

Besoin d'aide sur Next.js ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que Next.js ?
Next.js est un framework React open source qui permet de construire des applications web modernes et performantes avec React.
Comment installer Next.js ?
Pour installer Next.js, vous devez d'abord avoir Node.js sur votre ordinateur. Ensuite, vous pouvez utiliser la commande 'npx create-next-app@latest mon-projet' pour créer un nouveau projet Next.js.
Quelle est l'avantage de Next.js par rapport à React ?
Next.js offre des fonctionnalités supplémentaires comme le pré-rendu statique, les routes dynamiques et la récupération de données côté serveur, ce qui peut améliorer significativement les performances de votre application.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.