programmation

Coup de projecteurs sur l’une des plus simples et des plus puissantes APIs de Gatsby pour propulser vos sites.

Disclaimer

Je pars du principe que vous êtes au minimum sous Gatsby V2.1.31 !

Ce n’est pas une revue exhaustive de l’API mais plutôt un petit tour d’horizon des features qui m’ont le plus séduit.

Objectif Ux

Une navigation fluide c’est important pour l’expérience utilisateur (Ux). Plus je parcours la doc de Gatsby plus j’en apprécie la conception. Vraiment il faut le reconnaître : c’est du très haut niveau rendu très accessible.

L’ une des premières APIs que je vous invite à découvrir est l’API Link car le rendu est vraiment immédiat et la différence avec un site « traditionnel » est tout à fait claire.

Par rapport à un lien classique du type :

export default() => (
    <a href="/contact">Me contacter</a>
)

que vous réserverez désormais, dans Gatsby, aux liens externes, utilisez plutôt le composant Link de Gatsby pour tous vos liens internes :

import {Link} from "gatsby"

export default() => (
    <Link to={"/contact"}>Me contacter</Link>
)

Vous aurez une navigation débarrassée de cet effet désagréable de rechargement de page qui entraîne un flash visuellement.

Le but de Gatsby est d’avoir, au contraire, un effet d’affichage instantané. Une expérience hyper fluide qu’on retrouve habituellement dans les applis et les PWAs.

La seule différence notable dans la syntaxe, vous l’aurez peut-être remarqué, est qu’on utilise un paramètre to à la place de href. En revanche, l’impact sur l’Ux globale et la navigation du site est assez fort je trouve.

C’est donc facile à modifier et le gain est directement perceptible.

Une API riche

Il y a certains incontournables dans le web, parmi ceux-là, on retrouve le fait de signaler la page, la section en cours dans le menu de navigation.

L’API Link nous permet de mettre ça en place de manière ultra-simple !

activeStyle et activeClassName

Soit vous stylisez directement le lien qui est en cours avec activeStyle, soit vous utilisez activeClassName pour ajouter une classe, soit d’ailleurs vous combinez les deux !

Prenons le composant Menu.js suivant :

import React from "react"
import {Link} from "gatsby"

export default (props) => (
    <nav>
        {props.items.map(item => {
            return (
                <Link key={item.slug}
                      activeClassName="active"
                      className="menu-item"
                      to={item.url}
                >
                    {item.title}
                </Link>
                )
            })
        }
    </nav>
)

Ici je n’ai pas exactement repris l’exemple de la documentation avec des liens « manuels » car je trouvais ça plus parlant en termes de dév avec des données issues d’un tableau.

Je m’explique : ici je n’ai pas besoin de me lancer dans des conditions alambiquées pour essayer d’aller matcher pour chaque ligne de mon tableau (qui représente mon menu de navigation) celle qui correspond à la page en cours.

Gatsby m’a directement abstrait ça ! Dans mon CSS, je fais ensuite classiquement :

.menu-item.active {
/* mes styles */
}

Pour ceux qui préfèrent le styles inlines, utilisez activeStyle pour passer un objet de style uniquement à l’item de menu qui correspond à la page en cours.

Passer des infos dans les liens

Easy money !

On peut passer un « state » dans chaque lien ! Et dans ce « state » on peut mettre les infos dont on a besoin.

Imaginons dans le composant ContactLink suivant :

import React from "react"
import {Link} from "gatsby"

export default() => (
    <Link to={"/contact"} state={ isFromHell: true }>Me contacter</Link>
)

Je pourrais utiliser ce « state » sur la page contact :

import React from "react"

export default({location}) => {
    if (location.state.isFromHell) {
        return <p>Vous revenez de l'enfer !</p>
    } else {
        return <p>Vous avez fait bon chemin.</p>
    }
}

Je le répète, l’info sera transmise via ce state depuis la page émettrice vers la page d’arrivée.

D’une page à l’autre, certes, mais si vous avez besoin de passer par un lien (une page) intermédiaire pour une raison X notez qu’il vous sera possible de refiler votre state location.state.isFromHell dans le state du lien intermédiaire comme suit :

import React from "react"
import {Link} from "gatsby"

export default({location}) => (
    <Link to={"/contact"} state={ isFromHell: location.state.isFromHell }>Me contacter</Link>
)

Naviguer depuis le code

Là encore c’est « bougrement » bien fichu, avec navigate, on peut non seulement déclencher depuis le code une navigation comme si l’utilisateur cliquait sur un lien (avec le composant Link et tous ses avantages qui plus est) mais on peut aussi passer des données sur la page d’arrivée !

import React from "react"
import { navigate } from "gatsby"

const Form = () => (
  <form
    onSubmit={event => {
      event.preventDefault()

      // Implementation of this function is an exercise for the reader.
      const formValues = getFormValues()

      navigate(
        "/form-submitted/",
        {
          state: { formValues },
        }
      )
    }}
  >
    {/* (skip form inputs for brevity) */}
  </form>
)

Source

Remarque : ici le code issue de la doc officielle est à titre d’exemple, getFormValues() n’est pas définie par exemple.

Ce qu’il faut retenir est que le formulaire redirigera vers votre page de confirmation comme un lien interne Gatsby donc avec une fluidité maximale sans recharger la page.

Bien vu lulu !

Un bon petit conseil est donné pour les contenus issus de CMS comme c’est le cas de ce blog :

On ne peut pas savoir si les liens dans le post content (par exemple si on tire les data de WordPress) sont externes ou internes à l’avance. Pour cela un début de code est fourni :

import { Link as GatsbyLink } from "gatsby"

// Since DOM elements <a> cannot receive activeClassName
// and partiallyActive, destructure the prop here and
// pass it only to GatsbyLink
const Link = ({ children, to, activeClassName, partiallyActive, ...other }) => {
  // Tailor the following test to your environment.
  // This example assumes that any internal link (intended for Gatsby)
  // will start with exactly one slash, and that anything else is external.
  const internal = /^\/(?!\/)/.test(to)

  // Use Gatsby Link for internal links, and <a> for others
  if (internal) {
    return (
      <GatsbyLink
        to={to}
        activeClassName={activeClassName}
        partiallyActive={partiallyActive}
        {...other}
      >
        {children}
      </GatsbyLink>
    )
  }
  return (
    <a href={to} {...other}>
      {children}
    </a>
  )
}

export default Link

Une optimisation qui m’avait échappé même si je fais assez rarement des liens internes dans les billets de ce blog (ce qui est recommandé pour le maillage SEO) et que je prévois donc de rajouter prochainement 🙂

Mise à jour du 30/12/2019

Pour éviter de réinventer la roue, j’ai eu recours au plugin Gatsby catch links. Il s’occupe de transformer toutes les occurrences de liens internes en Link Gatsby !

Transition yikes !

L’API Link est totalement hors de cause ici mais le sujet est connexe. Je vous conseille chaudement d’éviter toutes les librairies et autres packages qui proposent de gérer des transitions de page avec animation.

J’ai testé et, bien que ce soit assez facile à implémenter, je trouve cela anti-Ux au final. En tous les cas, la manière actuelle, hacky, ne me convient pas du tout au moment d’écrire ce billet.

Vous savez ces animations qui rajoutent un délai au chargement entre chaque page du site et nous proposent un loader svg ou des effets CSS. Les tests sur ce petit blog effectués avec des plugins Gatsby dédiés ont tous engendré des bugs en série du type ça marche avec Chrome et fuck le reste du monde.

Vraiment faire attention avec ce genre de feature. Je ne dis pas que c’est impossible à réussir mais soyez prudents.

L’ API Link est plus simple, native et avec un résultat plus probant à mon avis.

Conclusion

L’API Link de Gatsby rend la navigation interne de vos sites fluide et agréable, il serait dommage de s’en priver en passant par des balises lien classiques à la place.

Mieux vaut donc réserver ces liens classiques aux liens externes et accéder ainsi à un affichage des pages quasi instantané.

Les composants fournis par l’API permettent aussi de transmettre assez facilement des données d’une page à l’autre.