Utiliser une librairie classique dans React

Dans cette vidéo je vous propose de découvrir comment intégrer une librairie non react dans react.

ref & useEffect()

De manière générale les librairies ont besoin de se greffer sur un élément dans le DOM aussi il faudra créer une référence pour obtenir l'élément. Ensuite, on initialisera la librairie lorsque le composant est monté.

import React, {useRef, useEffect} from 'react'
import flatpickr from 'flatpickr'

import 'flatpickr/dist/themes/confetti.css'

export function Datepicker ({value, onChange}) {
  const inputRef = useRef()

  // On initialise flatpickr
  useEffect(() => {
    if (inputRef.current) {
      flatpickr(inputRef.current)
      return () => f.destroy()
    }
  }, [inputRef.current])

  return <input ref={inputRef} type="text" value={value} onChange={onChange} />
}

Il faudra aussi et surtout penser à retourner une fonction qui permettra de détacher la librairie lorsque le composant sera démonté (pour éviter les effets de bord).

Synchroniser la valeur

Maintenant il faut aussi penser à ajouter le comportement qui permet de synchroniser la valeur, mais aussi de remonter les changements. Il sera souvent nécessaire de créer une référence pour mémoriser l'instance de notre librairie.

export function Datepicker ({value, onChange}) {
  const flatpickrRef = useRef()

  // ...

  useEffect(() => {
    if (inputRef.current) {
      const f = flatpickr(inputRef.current, {
        onChange: handleChange
      })
      flatpickrRef.current = f
      return () => f.destroy()
    }
  }, [inputRef.current])

  // Quand la valeur change on met à jour sur flatpickr
  useEffect(() => {
    if (flatpickrRef.current) {
      flatpickrRef.current.setDate(value, false)
    }
  }, [value])

  // ...
}

Attention cependant, le callback reçu en paramètre (ici onChange) peut être amené à changer. Il faut donc prévoir ce cas et mettre à jour l'instance.

export function Datepicker ({value, onChange}) {
  useEffect(() => {
    if (flatpickrRef.current) {
      flatpickrRef.set('onChange', (_, date) => onChange(date))
    }
  }, [onChange])
}

Une autre solution (si la librairie ne permet pas de changer les callback après l'initialisation) consiste à utiliser une référence pour le callback.

export function Datepicker ({value, onChange}) {
  // ...
  const onChangeRef = useRef(onChange)
  onChangeRef.current = onChange
  const handleChange = useCallback((_, date) => {
    onChangeRef.current(date)
  }, [])

  // On initialise flatpickr
  useEffect(() => {
    if (inputRef.current) {
      const f = flatpickr(inputRef.current, {
        onChange: handleChange
      })
      flatpickrRef.current = f
      return () => f.destroy()
    }
  }, [inputRef.current])

  // ...
}

Et voila !

Pour résumer

  • Initialiser la librairie à l'aide du useEffect
  • Utilisez la fonction de nettoyage pour supprimer les effets de bords
  • Gérer les changements de props (callback par exemple mais aussi les changements de valeur)
Publié
Technologies utilisées
Auteur :
Grafikart
Partager