Aller au contenu

e

Styliser vos applications React

L'apparence de notre application actuelle est assez modeste. Dans l'exercice 0.2, le travail consistait à suivre le tutoriel CSS de Mozilla.

Avant de passer à la partie suivante, voyons comment ajouter des styles à une application React. Il existe plusieurs façons de procéder et nous verrons les autres méthodes plus tard. Tout d'abord, nous allons ajouter CSS à notre application à l'ancienne ; dans un seul fichier sans utiliser de préprocesseur CSS (bien que ce ne soit pas tout à fait vrai comme nous le verrons plus tard).

Ajoutons un nouveau fichier index.css sous le répertoire src puis ajoutons-le à l'application en l'important dans le fichier index.js :

import './index.css'

Ajoutons la règle CSS suivante au fichier index.css :

h1 {
  color: green;
}

Remarque : lorsque le contenu du fichier index.css change, React peut ne pas le remarquer automatiquement, vous devrez donc peut-être actualiser le navigateur pour voir vos modifications !

Les règles CSS comprennent des sélecteurs et des déclarations. Le sélecteur définit les éléments auxquels la règle doit être appliquée. Le sélecteur ci-dessus est h1, qui correspondra à toutes les balises d'en-tête h1 de notre application.

La déclaration définit la propriété color sur la valeur green.

Une règle CSS peut contenir un nombre arbitraire de propriétés. Modifions la règle précédente pour rendre le texte cursif, en définissant le style de police en italique :

h1 {
  color: green;
  font-style: italic;}

Il existe de nombreuses façons de faire correspondre des éléments en utilisant différents types de sélecteurs CSS.

Si nous voulions cibler, disons, chacune des notes avec nos styles, nous pourrions utiliser le sélecteur li, car toutes les notes sont enveloppées dans des balises li :

const Note = ({ note, toggleImportance }) => {
  const label = note.important 
    ? 'make not important' 
    : 'make important';

  return (
    <li>
      {note.content} 
      <button onClick={toggleImportance}>{label}</button>
    </li>
  )
}

Ajoutons la règle suivante à notre feuille de style (puisque ma connaissance de la conception Web élégante est proche de zéro, les styles n'ont pas beaucoup de sens) :

li {
  color: grey;
  padding-top: 3px;
  font-size: 15px;
}

L'utilisation de types d'éléments pour définir des règles CSS est légèrement problématique. Si notre application contenait d'autres balises li, la même règle de style leur serait également appliquée.

Si nous voulons appliquer notre style spécifiquement aux notes, il est préférable d'utiliser class selectors.

En HTML normal, les classes sont définies comme la valeur de l'attribut class :

<li class="note">some text...</li>

Dans React, nous devons utiliser l'attribut className au lieu de l'attribut class. Gardant cela à l'esprit, apportons les modifications suivantes à notre composant Note :

const Note = ({ note, toggleImportance }) => {
  const label = note.important 
    ? 'make not important' 
    : 'make important';

  return (
    <li className='note'>      {note.content} 
      <button onClick={toggleImportance}>{label}</button>
    </li>
  )
}

Les sélecteurs de classe sont définis avec la syntaxe .classname :

.note {
  color: grey;
  padding-top: 5px;
  font-size: 15px;
}

Si vous ajoutez maintenant d'autres éléments li à l'application, ils ne seront pas affectés par la règle de style ci-dessus.

Message d'erreur amélioré

Nous avons précédemment implémenté le message d'erreur qui s'affichait lorsque l'utilisateur tentait de modifier l'importance d'une note supprimée avec la méthode alert. Implémentons le message d'erreur comme son propre composant React.

Le composant est assez simple :

const Notification = ({ message }) => {
  if (message === null) {
    return null
  }

  return (
    <div className='error'>
      {message}
    </div>
  )
}

Si la valeur de la prop message est null, alors rien n'est rendu à l'écran, et dans d'autres cas, le message est rendu à l'intérieur d'un élément div.

Ajoutons un nouvel élément d'état appelé errorMessage au composant App. Initialisons-le avec un message d'erreur afin que nous puissions immédiatement tester notre composant :

const App = () => {
  const [notes, setNotes] = useState([]) 
  const [newNote, setNewNote] = useState('')
  const [showAll, setShowAll] = useState(true)
  const [errorMessage, setErrorMessage] = useState('some error happened...')
  // ...

  return (
    <div>
      <h1>Notes</h1>
      <Notification message={errorMessage} />      <div>
        <button onClick={() => setShowAll(!showAll)}>
          show {showAll ? 'important' : 'all' }
        </button>
      </div>      
      // ...
    </div>
  )
}

Ajoutons ensuite une règle de style qui convient à un message d'erreur :

.error {
  color: red;
  background: lightgrey;
  font-size: 20px;
  border-style: solid;
  border-radius: 5px;
  padding: 10px;
  margin-bottom: 10px;
}

Nous sommes maintenant prêts à ajouter la logique pour afficher le message d'erreur. Modifions la fonction toggleImportanceOf de la manière suivante :

  const toggleImportanceOf = id => {
    const note = notes.find(n => n.id === id)
    const changedNote = { ...note, important: !note.important }

    noteService
      .update(changedNote).then(returnedNote => {
        setNotes(notes.map(note => note.id !== id ? note : returnedNote))
      })
      .catch(error => {
        setErrorMessage(          `Note '${note.content}' was already removed from server`        )        setTimeout(() => {          setErrorMessage(null)        }, 5000)        setNotes(notes.filter(n => n.id !== id))
      })
  }

Lorsque l'erreur se produit, nous ajoutons un message d'erreur descriptif à l'état errorMessage. En même temps, nous démarrons une minuterie, qui définira l'état errorMessage sur null après cinq secondes.

Le résultat ressemble à ceci :

fullstack content

Le code de l'état actuel de notre application se trouve sur la branche part2-7 sur GitHub.

Styles en ligne

React permet également d'écrire des styles directement dans le code en tant que inline-styles.

L'idée derrière la définition des styles en ligne est extrêmement simple. Tout composant ou élément React peut être fourni avec un ensemble de propriétés CSS en tant qu'objet JavaScript via l'attribut style.

Les règles CSS sont définies légèrement différemment dans JavaScript que dans les fichiers CSS normaux. Disons que nous voulions donner à un élément la couleur verte et une police en italique d'une taille de 16 pixels. En CSS, cela ressemblerait à ceci :

{
  color: green;
  font-style: italic;
  font-size: 16px;
}

Mais en tant qu'objet de style en ligne React, cela ressemblerait à ceci :

{
  color: 'green',
  fontStyle: 'italic',
  fontSize: 16
}

Chaque propriété CSS est définie comme une propriété distincte de l'objet JavaScript. Les valeurs numériques des pixels peuvent être simplement définies comme des nombres entiers. L'une des principales différences par rapport au CSS standard est que les propriétés CSS avec trait d'union (kebab case) sont écrites en camelCase.

Ensuite, nous pourrions ajouter un "bloc inférieur" à notre application en créant un composant Footer et en définissant les styles en ligne suivants pour celui-ci:

const Footer = () => {  const footerStyle = {    color: 'green',    fontStyle: 'italic',    fontSize: 16  }  return (    <div style={footerStyle}>      <br />      <em>Note app, Department of Computer Science, University of Helsinki 2022</em>    </div>  )}
const App = () => {
  // ...

  return (
    <div>
      <h1>Notes</h1>

      <Notification message={errorMessage} />

      // ...  

      <Footer />    </div>
  )
}

Les styles en ligne comportent certaines limitations. Par exemple, les soi-disant pseudo-classes ne peuvent pas être utilisées directement.

Les styles en ligne et certaines des autres façons d'ajouter des styles aux composants React vont complètement à l'encontre des anciennes conventions. Traditionnellement, il a été considéré comme une bonne pratique de séparer entièrement CSS du contenu (HTML) et de la fonctionnalité (JavaScript). Selon cette ancienne école de pensée, l'objectif était d'écrire CSS, HTML et JavaScript dans leurs fichiers séparés.

La philosophie de React est, en fait, à l'opposé de cela. Étant donné que la séparation de CSS, HTML et JavaScript dans des fichiers séparés ne semblait pas bien évoluer dans les applications plus grandes, React fonde la division de l'application sur les lignes de ses entités fonctionnelles logiques.

Les unités structurelles qui composent les entités fonctionnelles de l'application sont des composants React. Un composant React définit le HTML pour structurer le contenu, les fonctions JavaScript pour déterminer les fonctionnalités, ainsi que le style du composant ; tout en un seul endroit. Il s'agit de créer des composants individuels aussi indépendants et réutilisables que possible.

Le code de la version finale de notre application se trouve sur la branche part2-8 sur GitHub.