Partage via


Créer une application React dans Visual Studio

Dans ce tutoriel, vous allez créer une interface frontale React pour une application web de gestion de listes to-do, à l’aide de JavaScript et de Visual Studio 2022. Le code de cette application se trouve à ToDoJSWebApp.

Conditions préalables

Veillez à installer les éléments suivants :

Créer l’application React ToDo List

  1. Dans Visual Studio, sélectionnez Fichier > Nouveau > Projet pour ouvrir la boîte de dialogue Créer un nouveau projet, sélectionnez le modèle JavaScript application React, puis choisissez suivant.

    Capture d’écran montrant le choix d’un modèle.

  2. Nommez le projet TodoWebApp et sélectionnez Créer.

    L'outil en ligne de commande vitecrée ainsi le projet JavaScript.

  3. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier src et choisissez Ajouter > nouveau dossier. et créez un dossier nommé components.

    Il s’agit d’une convention commune pour placer des composants dans un dossier de composants, mais cela n’est pas obligatoire.

  4. Cliquez avec le bouton droit sur le nouveau dossier, sélectionnez Ajouter > fichier de composant React JSX, nommez-le TodoList, puis cliquez sur Ajouter.

    Capture d’écran montrant l’ajout d’un composant JSX.

    Cela crée un fichier JSX dans le dossier des composants.

  5. Ouvrez le composant TodoList et remplacez le contenu par défaut par les éléments suivants :

    function TodoList() {
      return (
        <h2>TODO app contents</h2>
      );
    }
    

    Ce composant affiche un en-tête, que vous remplacerez ultérieurement.

    Ensuite, configurez ce composant dans l’application. App.jsx est le composant principal chargé, qui représente l’application de liste to-do. Ce composant est utilisé dans le fichier main.jsx.

  6. Dans l’Explorateur de solutions, ouvrez App.jsx, supprimez toutes les importations du haut et effacez le contenu de l’instruction return. Le fichier doit ressembler à ce qui suit.

    function App() {
      return (
        <>
          <TodoList />
        </>
      );
    }
    export default App;
    
  7. Pour ajouter le composant TodoList, placez votre curseur à l’intérieur du fragment, puis tapez <TodoL RETURN. Cela ajoute le composant et l’instruction import.

    capture d’écran montrant l’ajout d’un composant JSX à l’application.

    Ensuite, effacez les fichiers CSS.

  8. Ouvrez App.css et supprimez tout le contenu.

  9. Ouvrez Index.css et supprimez tout le contenu, à l’exception des styles de :root:

    :root {
      font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
      line-height: 1.5;
      font-weight: 400;
      color-scheme: light dark;
      color: rgba(255, 255, 255, 0.87);
      background-color: #242424;
    }
    

Exécuter l’application

Sélectionnez le bouton Démarrer le débogage dans la barre d’outils ou appuyez sur le raccourci clavier F5.

L’application s’ouvre dans une fenêtre de navigateur.

Capture d’écran montrant l’application en cours d’exécution dans le navigateur.

Ajouter des fonctions de liste to-do à l'application

Vous pouvez laisser l’application en cours d’exécution. Lorsque vous apportez des modifications, l’application s’actualise automatiquement avec le contenu le plus récent à l’aide de la prise en charge du remplacement de module chaud de Vite. Certaines actions, telles que l’ajout de dossiers ou de renommage de fichiers, nécessitent que vous arrêtiez le débogage, puis redémarrez l’application, mais en général, vous pouvez la laisser en cours d’exécution en arrière-plan lorsque vous développez votre application. Ouvrez le composant TodoList.jsx pour commencer à le définir.

  1. Dans l’Explorateur de solutions, ouvrez TodoList.jsx et ajoutez l’interface utilisateur nécessaire pour afficher et gérer les entrées de liste to-do. Remplacez le contenu par le code suivant :

    function TodoList() {
      return (
        <div>
          <h1>TODO</h1>
          <div>
            <input type="text" placeholder="Enter a task" required aria-label="Task text" />
            <button className="add-button" aria-label="Add task">Add</button>
          </div>
          <ol id="todo-list">
            <p>existing tasks will be shown here</p>
          </ol>
        </div>
      );
    }
    export default TodoList;
    

    Le code précédent ajoute une zone d’entrée pour la nouvelle tâche to-do et un bouton pour envoyer l’entrée. Ensuite, vous connectez le bouton Ajouter. Utilisez le useState Hook React pour ajouter deux variables d’état, une pour la tâche qui est ajoutée et une autre pour stocker les tâches existantes. Pour ce tutoriel, les tâches sont stockées en mémoire et non dans le stockage persistant.

  2. Ajoutez l’instruction d’importation suivante à TodoList.jsx pour importer useState.

    import { useState } from 'react'
    
  3. Ensuite, utilisez ce hook pour créer les variables d’état. Ajoutez le code suivant dans la fonction TodoList au-dessus de l’instruction return.

    const [tasks, setTasks] = useState(["Drink some coffee", "Create a TODO app", "Drink some more coffee"]);
    const [newTaskText, setNewTaskText] = useState("");
    

    Cette opération configure deux variables, tasks et newTaskText, pour les données et deux fonctions que vous pouvez appeler pour mettre à jour ces variables, setTasks et setNewTasks. Lorsqu’une valeur pour une variable d’état est modifiée, React restitue automatiquement le composant.

    Vous êtes presque prêt à mettre à jour TodoList.jsx pour afficher les éléments to-do sous forme de liste, mais il existe un concept React important à apprendre en premier.

    Dans React, lorsque vous affichez une liste d’éléments, vous devez ajouter une clé pour identifier de manière unique chaque élément de la liste. Cette fonctionnalité est expliquée en détail dans la documentation React dans Listes de rendu, mais ici, vous allez apprendre les principes de base. Vous disposez d’une liste de to-do éléments à afficher et vous devez associer une clé unique pour chaque élément. La clé de chaque élément ne doit pas changer et, pour cette raison, vous ne pouvez pas utiliser l’index de l’élément dans le tableau comme clé. Vous avez besoin d’un ID qui ne changera pas tout au long de la durée de vie de ces valeurs. Vous utiliserez randomUUID() pour créer un ID unique pour chaque élément to-do.

  4. Créez TodoList.jsx à l’aide d’un UUID comme clé pour chaque élément to-do. Mettez à jour TodoList.jsx avec le code suivant.

    import React, { useState } from 'react';
    
    const initialTasks = [
        { id: self.crypto.randomUUID(), text: 'Drink some coffee' },
        { id: self.crypto.randomUUID(), text: 'Create a TODO app' },
        { id: self.crypto.randomUUID(), text: 'Drink some more coffee' }
    ];
    
    function TodoList() {
        const [tasks, setTasks] = useState(initialTasks);
        const [newTaskText, setNewTaskText] = useState("");
    
        return (
            <article
                className="todo-list"
                aria-label="task list manager">
                <header>
                    <h1>TODO</h1>
                    <form className="todo-input" aria-controls="todo-list">
                        <input
                            type="text"
                            placeholder="Enter a task"
                            value={newTaskText} />
                        <button
                            className="add-button">
                            Add
                        </button>
                    </form>
                </header>
                <ol id="todo-list" aria-live="polite" aria-label="task list">
                    {tasks.map((task, index) =>
                        <li key={task.id}>
                            <span className="text">{task.text}</span>
                        </li>
                    )}
                </ol>
            </article>
        );
    }
    export default TodoList;
    

    Étant donné que les valeurs d’ID sont affectées en dehors de la fonction TodoList, vous pouvez être sûr que les valeurs ne changeront pas si la page est réexécrite. Lorsque vous essayez l’application dans cet état, vous remarquerez que vous ne pouvez pas taper dans l’élément d’entrée todo. Cela est dû au fait que l’élément d’entrée est lié à newTaskText, qui a été initialisé dans une chaîne vide. Pour permettre aux utilisateurs d’ajouter de nouvelles tâches, vous devez gérer l’événement onChange sur ce contrôle. Vous devez également implémenter la prise en charge du bouton Ajouter.

  5. Ajoutez les fonctions requises immédiatement avant l’instruction return dans la fonction TodoList.

    function handleInputChange(event) {
        setNewTaskText(event.target.value);
    }
    
    function addTask() {
        if (newTaskText.trim() !== "") {
            setTasks(t => [...t, { id: self.crypto.randomUUID(), text: newTaskText }]);
            setNewTaskText("");
        }
        event.preventDefault();
    }
    

    Dans la fonction handleInputChanged, la nouvelle valeur du champ d’entrée est transmise via event.target.value, et cette valeur est utilisée pour mettre à jour la valeur de la variable newTaskText avec setNewTaskText. Dans la fonction addTask, ajoutez la nouvelle tâche à la liste des tâches existantes à l’aide de setTasks et définissez l’ID de l’élément comme nouvelle valeur UUID. Mettez à jour l’élément d’entrée pour inclure onChange={handleInputChange} et mettez à jour le bouton Ajouter pour inclure onClick={addTask}. Ce code relie l’événement à la fonction qui gère cet événement. Après cela, vous devez être en mesure d’ajouter une nouvelle tâche à la liste des tâches. Les nouvelles tâches sont ajoutées au bas de la liste. Pour rendre cette application plus utile, vous devez ajouter la prise en charge pour supprimer des tâches et déplacer une tâche vers le haut ou vers le bas.

  6. Ajoutez les fonctions pour prendre en charge la suppression, monter et descendre vers le bas, puis mettez à jour le balisage pour afficher un bouton pour chaque action. Ajoutez le code suivant dans la fonction TodoList au-dessus de l’instruction return.

    function deleteTask(id) {
        const updatedTasks = tasks.filter(task => task.id != id);
        setTasks(updatedTasks);
    }
    
    function moveTaskUp(index) {
        if (index > 0) {
            const updatedTasks = [...tasks];
            [updatedTasks[index], updatedTasks[index - 1]] = [updatedTasks[index - 1], updatedTasks[index]];
            setTasks(updatedTasks);
        }
    }
    
    function moveTaskDown(index) {
        if (index < tasks.length) {
            const updatedTasks = [...tasks];
            [updatedTasks[index], updatedTasks[index + 1]] = [updatedTasks[index + 1], updatedTasks[index]];
            setTasks(updatedTasks);
        }
    }
    

    La fonction delete prend l’ID de tâche et supprime celle-ci de la liste et utilise la méthode Array filter() pour créer un tableau à l’exclusion de l’élément sélectionné, puis appelle setTasks(). Les deux autres fonctions prennent en entrée l’index de l’élément, car cela est spécifique à l'ordre des éléments. moveTaskUp() et moveTaskDown() utilisent l'affectation par déstructuration de tableau pour permuter la tâche sélectionnée avec celle de son voisin.

  7. Ensuite, mettez à jour la vue pour inclure ces trois boutons. Mettez à jour l’instruction return pour contenir les éléments suivants.

    return (
        <article
            className="todo-list"
            aria-label="task list manager">
            <header>
                <h1>TODO</h1>
                <form className="todo-input" onSubmit={addTask} aria-controls="todo-list">
                    <input
                        type="text"
                        required
                        autoFocus
                        placeholder="Enter a task"
                        value={newTaskText}
                        aria-label="Task text"
                        onChange={handleInputChange} />
                    <button
                        className="add-button"
                        aria-label="Add task">
                        Add
                    </button>
                </form>
            </header>
            <ol id="todo-list" aria-live="polite">
                {tasks.map((task, index) =>
                    <li key={task.id}>
                        <span className="text">{task.text}</span>
                        <button className="delete-button" onClick={() => deleteTask(task.id)}>
                            🗑️
                        </button>
                        <button className="up-button" onClick={() => moveTaskUp(index)}>
                            ⇧
                        </button>
                        <button className="down-button" onClick={() => moveTaskDown(index)}>
                            ⇩
                        </button>
                    </li>
                )}
            </ol>
        </article>
    );
    

    Vous avez ajouté les boutons nécessaires pour effectuer les tâches que nous avons abordées précédemment. Vous utilisez des caractères Unicode comme icônes sur les boutons. Dans le balisage, certains attributs sont ajoutés pour prendre en charge l’ajout de css ultérieurement. Vous pouvez également remarquer l’utilisation d’attributs d’aria pour améliorer l’accessibilité, qui sont facultatifs mais fortement recommandés. Si vous exécutez l’application, elle doit ressembler à l’illustration suivante.

    capture d’écran montrant l’application en cours d’exécution et montrant une liste

    Vous devez maintenant être en mesure d’effectuer les opérations suivantes dans l’application web TODO.

    • Ajouter une tâche
    • Supprimer la tâche
    • Déplacer la tâche vers le haut
    • Déplacer la tâche vers le bas

    Ces fonctions fonctionnent, mais vous pouvez refactoriser pour créer un composant réutilisable pour afficher les éléments to-do. Le balisage de l’élément to-do entre dans un nouveau composant, TodoItem. Étant donné que la gestion de la liste reste dans le composant Todo, vous pouvez passer des rappels aux boutons Supprimer et Déplacer.

  8. Pour commencer, cliquez avec le bouton droit sur le dossier composants dans l’Explorateur de solutions, puis sélectionnez Ajouter > nouvel élément.

  9. Dans la boîte de dialogue qui s’ouvre, sélectionnez le fichier de composant React JSX , nommez-le TodoItem, puis sélectionnez Ajouter.

  10. Ajoutez le code suivant à l’objet TodoItem.

    Dans ce code, vous transmettez la tâche et les rappels en tant que propriétés à ce nouveau composant.

    import PropTypes from 'prop-types';
    
    function TodoItem({ task, deleteTaskCallback, moveTaskUpCallback, moveTaskDownCallback }) {
        return (
            <li aria-label="task" >
                <span className="text">{task}</span>
                <button
                    type="button"
                    aria-label="Delete task"
                    className="delete-button"
                    onClick={() => deleteTaskCallback()}>
                    🗑️
                </button>
                <button
                    type="button"
                    aria-label="Move task up"
                    className="up-button"
                    onClick={() => moveTaskUpCallback()}>
                    ⇧
                </button>
                <button
                    type="button"
                    aria-label="Move task down"
                    className="down-button"
                    onClick={() => moveTaskDownCallback()}>
                    ⇩
                </button>
            </li>
        );
    }
    
    TodoItem.propTypes = {
        task: PropTypes.string.isRequired,
        deleteTaskCallback: PropTypes.func.isRequired,
        moveTaskUpCallback: PropTypes.func.isRequired,
        moveTaskDownCallback: PropTypes.func.isRequired,
    };
    
    export default TodoItem;
    

    Le code précédent contient le balisage du composant Todo et à la fin de celui-ci, vous déclarez le PropTypes. Les propriétés sont utilisées pour transmettre des données d’un composant parent aux composants enfants. Pour plus d’informations sur les propriétés, consultez Passage de propriétés à un composant – React. Étant donné que les fonctions de suppression et de déplacement sont passées en tant que rappels, le gestionnaire onClick doit être mis à jour pour appeler ces rappels.

  11. Ajoutez le code requis. Le code complet de TodoList qui utilise le composant TodoItem est illustré ici.

    import React, { useState } from 'react'
    import TodoItem from './TodoItem'
    
    const initialTasks = [
        { id: self.crypto.randomUUID(), text: 'Drink some coffee' },
        { id: self.crypto.randomUUID(), text: 'Create a TODO app' },
        { id: self.crypto.randomUUID(), text: 'Drink some more coffee' }
    ];
    
    function TodoList() {
        const [tasks, setTasks] = useState(initialTasks);
        const [newTaskText, setNewTaskText] = useState("");
        function handleInputChange(event) {
            setNewTaskText(event.target.value);
        }
        function addTask() {
            if (newTaskText.trim() !== "") {
                setTasks(t => [...t, { id: self.crypto.randomUUID(), text: newTaskText }]);
                setNewTaskText("");
            }
            event.preventDefault();
        }
        function deleteTask(id) {
            const updatedTasks = tasks.filter(task => task.id !== id);
            setTasks(updatedTasks);
        }
        function moveTaskUp(index) {
            if (index > 0) {
                const updatedTasks = [...tasks];
                [updatedTasks[index], updatedTasks[index - 1]] = [updatedTasks[index - 1], updatedTasks[index]];
                setTasks(updatedTasks);
            }
        }
        function moveTaskDown(index) {
            if (index < tasks.length) {
                const updatedTasks = [...tasks];
                [updatedTasks[index], updatedTasks[index + 1]] = [updatedTasks[index + 1], updatedTasks[index]];
                setTasks(updatedTasks);
            }
        }
        return (
            <article
                className="todo-list"
                aria-label="task list manager">
                <header>
                    <h1>TODO</h1>
                    <form onSubmit={addTask} aria-controls="todo-list">
                        <input
                            type="text"
                            required
                            placeholder="Enter a task"
                            value={newTaskText}
                            aria-label="Task text"
                            onChange={handleInputChange} />
                        <button
                            className="add-button"
                            aria-label="Add task">
                            Add
                        </button>
                    </form>
                </header>
                <ol id="todo-list" aria-live="polite">
                    {tasks.map((task, index) =>
                        <TodoItem
                            key={task.id}
                            task={task.text}
                            deleteTaskCallback={() => deleteTask(task.id)}
                            moveTaskUpCallback={() => moveTaskUp(index)}
                            moveTaskDownCallback={() => moveTaskDown(index)}
                        />
                    )}
                </ol>
            </article>
        );
    }
    
    export default TodoList;
    

    À présent, le composant TodoItem est utilisé pour afficher chaque élément to-do. Notez que la clé est définie sur task.id, qui contient la valeur UUID pour cette tâche. Lorsque vous exécutez l’application, vous ne devez pas voir les modifications apportées à l’apparence ou au comportement de l’application, car vous l’avez refactorisé pour utiliser TodoItem.

    Maintenant que vous avez toutes les fonctions de base prises en charge, il est temps de commencer à ajouter un style à cela pour le rendre agréable. Commencez par ajouter un lien dans Index.html pour une famille de polices, Inter, que vous utiliserez pour cette application. Dans Index.html, il existe d’autres éléments qui doivent être nettoyés. Plus précisément, le titre doit être mis à jour et vous souhaitez remplacer le fichier vite.svg actuellement utilisé comme icône.

  12. Mettez à jour Index.html avec le contenu suivant.

    <!doctype html>
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <link rel="icon" type="image/svg+xml" href="/checkmark-square.svg" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>TODO app</title>
            <link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'>
            <script type="module" defer src="/src/main.jsx"></script>
        </head>
        <body>
        </body>
    </html>
    
  13. Modifiez fichier main.jsx pour remplacer root par main lors de l’appel de createRoot.

    Le code complet de main.jsx est illustré ici.

    import { StrictMode } from 'react'
    import { createRoot } from 'react-dom/client'
    import App from './App.jsx'
    import './index.css'
    
    createRoot(document.querySelector('main')).render(
        <StrictMode>
            <App />
        </StrictMode>,
    )
    

    En plus de ces modifications, le fichier checkmark-square.svg a été ajouté au dossier public. Il s’agit d’un SVG provenant de l’image « carré à coche » de FluentUI, que vous pouvez télécharger directement. (Il existe un package que vous pouvez utiliser pour une expérience plus intégrée, mais ce n’est pas dans l’étendue de cet article.)

    Ensuite, mettez à jour les styles du composant TodoList.

  14. Dans le dossier des composants, ajoutez un nouveau fichier CSS nommé TodoList.css. Vous pouvez cliquer avec le bouton droit sur le projet et sélectionner Ajouter > nouvel élément, puis sélectionner feuille de style. Donnez au fichier le nom TodoList.css.

  15. Ajoutez le code suivant à TodoList.css.

    .todo-list {
        background-color: #1e1e1e;
        padding: 1.25rem;
        border-radius: 0.5rem;
        box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.3);
        width: 100%;
        max-width: 25rem;
    }
    
    .todo-list h1 {
        text-align: center;
        color: #e0e0e0;
    }
    
    .todo-input {
        display: flex;
        justify-content: space-between;
        margin-bottom: 1.25rem;
    }
    
    .todo-input input {
        flex: 1;
        padding: 0.625rem;
        border: 0.0625rem solid #333;
        border-radius: 0.25rem;
        margin-right: 0.625rem;
        background-color: #2c2c2c;
        color: #e0e0e0;
    }
    
    .todo-input .add-button {
        padding: 0.625rem 1.25rem;
        background-color: #007bff;
        color: #fff;
        border: none;
        border-radius: 0.25rem;
        cursor: pointer;
    }
    
    .todo-input .add-button:hover {
        background-color: #0056b3;
    }
    
    .todo-list ol {
        list-style-type: none;
        padding: 0;
    }
    
    .todo-list li {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0.625rem;
        border-bottom: 0.0625rem solid #333;
    }
    
    .todo-list li:last-child {
        border-bottom: none;
    }
    
    .todo-list .text {
        flex: 1;
    }
    
    .todo-list li button {
        background: none;
        border: none;
        cursor: pointer;
        font-size: 1rem;
        margin-left: 0.625rem;
        color: #e0e0e0;
    }
    
    .todo-list li button:hover {
        color: #007bff;
    }
    
    .todo-list li button.delete-button {
        color: #ff4d4d;
    }
    
    .todo-list li button.up-button,
    .todo-list li button.down-button {
        color: #4caf50;
    }
    
  16. Ensuite, modifiez TodoList.jsx pour ajouter l’importation suivante en haut du fichier.

    import './TodoList.css';
    
  17. Actualisez le navigateur après avoir enregistré les modifications. Cela doit améliorer le style de l’application. L’application doit ressembler à ce qui suit.

    Capture d’écran montrant la version finale de l’application en cours d’exécution.

    Vous avez maintenant créé une application de liste de to-do opérationnelle qui stocke les éléments to-do en mémoire. À partir de ce stade, vous pouvez mettre à jour l’application pour stocker les éléments to-do dans localStorage/IndexedDb, ou l’intégrer à une base de données côté serveur ou à un autre serveur principal, pour un stockage plus permanent.

Résumé

Dans ce tutoriel, vous avez créé une application React à l’aide de Visual Studio. L'application se compose d'une liste de to-do, qui permet d'ajouter des tâches, de supprimer des tâches et de les réorganiser. Vous avez créé deux nouveaux composants React et les avez utilisés tout au long de ce didacticiel.

Ressources