Tutoriel Vidéo Symfony React Module de commentaires : React

Télécharger la vidéo Télécharger les sources

La première partie de ce tutoriel est disponible ici

Dans ce second chapitre nous allons crée la partie interface de notre module de commentaires en nous basant sur la librairie React.

Avant de commencer il est important de réfléchir à la raison derrière l'utilisation de la librairie. Pour ce module de commentaire il y aura pas mal d'actions utilisateur et ses actions se traduisent par des changements au niveau de l'interface. Pour simplifier les transformations et la manipulation du DOM nous allons utiliser React. Il va nous permettre de représenter notre interface comme une fonction de l'état et on pourra ainsi se concentrer sur le changement de cet état (c’est React qui se chargera de synchroniser le dom et il nous offrira ainsi un niveau d’abstraction supplémentaire). On pourrait ici utiliser Preact si on souhaite une alternative plus légère et si on ne compte pas utiliser React dans le reste de notre application.

Les hooks

Pour ce genre de module nous allons avoir besoin de communiquer avec l'API et effectuer des opérations qu'ils sont très génériques. Typiquement nous allons appeler une URL, afficher un spinner pendant le chargement, et ensuite afficher les résultats. Cette logique étant très générique nous allons pouvoir l'extraire dans des couque que l'on pourra ensuite réutiliser tout au long de notre projet.

function Comments ({post, user}) {
  // Ce hook permet de gérer toute la partie récupération indépendamment du composant
  const {items: comments, setItems: setComments, loading, count, hasMore} = usePaginatedFetch('/api/comments?post=' + post)

  // On gère les mutations spécifiques à notre composant (mais on pourrait l'abstraire dans une fonction si cette logique se répète)
  const addComment = useCallback(comment => {
    setComments(comments => [comment, ...comments])
  }, [])
  const deleteComment = useCallback(comment => {
    setComments(comments => comments.filter(c => c !== comment))
  }, [])
  const updateComment = useCallback((newComment, oldComment) => {
    setComments(comments => comments.map(c => c === oldComment ? newComment : c))
  }, [])

  // On rend le composant
  return <div>
    <Title count={count}/>
    {user && <CommentForm post={post} onComment={addComment}/>}
    {comments.map(c =>
      <Comment
        key={c.id}
        comment={c}
        canEdit={c.author.id === user}
        onDelete={deleteComment}
        onUpdate={updateComment}
      />
    )}
    {hasMore && <button disabled={loading} className="btn btn-primary" onClick={load}>Charger plus de commentaire</button> }
  </div>
}

L'objectif des hooks est d'être capable de séparer les mutations de l’état de la partie interface.