Entre le moment où ils sont générés dans le DOM, et le moment où ils en sont retirés, les composants passent par différentes étapes. Dans les composants classe, vous avez une liste d'étapes qui correspondent à un moment précis du cycle de vie, dans lesquelles vous pouvez effectuer des actions.
On parle de méthodes de cycle de vie.
Découvrez les méthodes de cycle de vie
Dans le screencast juste en dessous, vous aurez une petite démonstration des différentes étapes que connaît un composant, et auxquelles vous pouvez accéder. 👇
Alors, est-ce que ça vous paraît plus clair ?
Pour vous faire un petit résumé des différentes étapes auxquelles vous avez accès dans les composants classe :
Comme vous l’avez vu dans le screencast :
Le
constructeur
est invoqué en premier, comme pour n’importe quel objet, lorsque le composant apparaît pour la première fois dans un DOM virtuel… Il reçoit les props initiales en argument.Puis vient le
render
. C’est ensuite le moment où est appelécomponentDidMount()
(une fois que le composant est monté sur le DOM).Après, s’il y a une mise à jour et que le composant est re-render,
componentDidUpdate
est appelé.Et juste avant que le composant soit retiré du DOM, c'est au tour de
componentWillUnmount
d'être appelé.
Il existe d'autres méthodes de cycle de vie, mais vous aurez moins souvent besoin de celles-ci. Vous pourrez en apprendre davantage dans la documentation de React.
Appelez une API dans un composant classe avec componentDidMount
C'est le moment de mettre tout ça en application en appelant notre API Shiny dans un nouveau composant classe. Pour l'occasion, nous allons créer un nouveau composant qui permet d'afficher plus d'informations sur un freelance lorsqu'on clique sur la Card
.
Nous allons commencer par permettre de naviguer surhttp://localhost/profile/:id
. Dans le fichier index.jsx
à la racine de /src
, nous avons ajouté une route pour bien rediriger l'utilisateur vers le profil du freelance :
...
<Route path="/freelances" element={<Freelances />} />
<Route path="/profile/:id" element={<Profile />} />
<Route path="*" element={<Error />} />
...
On enchaîne ensuite en permettant de naviguer sur la page profile
en ajoutant un lien autour de la Card
dans /pages/Freelances/index.jsx
. Pour cela, on fait donc :
<CardsContainer>
{freelancersList?.map((profile) => (
<Link key={`freelance-${profile.id}`} to={`/profile/${profile.id}`}>
<Card
label={profile.job}
title={profile.name}
picture={profile.picture}
theme={theme}
/>
</Link>
))}
</CardsContainer>
Et on n'oublie pas de supprimer la fonctionnalité de favoris dans le composant classe (pour ne pas avoir des étoiles ajoutées inutilement). Il ne nous reste plus qu'à développer pages/Profile/index.jsx
elle-même !
On va commencer par récupérer l' id
du freelance dont on veut afficher le profil dans les paramètres. Mais oh oh… Comment on va faire ?
Comme on l'avait fait pour la page Survey
: il nous suffit d'utiliser useParams
, non ?!
Eh bien non ! Souvenez-vous : les hooks sont uniquement accessibles depuis les composants fonction😢. D'ailleurs, la version 6 de React Router, sortie en 2021, soit 2 ans après la mise en place des hooks, est pensée pour être utilisée dans des composants fonctions. Nous avons donc ici 2 options:
Transformer le composant Profile en composant de type fonction.
Créer un composant qui sera parent de Profile et qui pourra récupérer les paramètres.
Comme nous souhaitons pour l'exemple créer notre composant Profile en Classe nous allons donc opter pour la deuxième option.
On va donc devoir changer la déclaration de notre route. Dans /src/index.jsx
, on fait donc :
<Route
path="/profile/:id"
element={<ProfileContainer />}
/>
Nous créons donc notre composant ProfileContainer que nous ajouterons à notre dossier components. Nous aurons donc un nouveau fichier index.jsx
dans le dossier src/components/ProfileContainer
avec ce code :
import { useParams } from 'react-router-dom'
import Profile from '../../pages/Profile'
function ProfileContainer() {
const { id } = useParams()
return <Profile id={id} />
}
export default ProfileContainer
Ensuite nous pourrons récupérer l'id dans notre classe Profile
comme n'importe quelle autre props :
import { Component } from 'react'
class Profile extends Component {
render() {
const { id } = this.props
return <div><h1>Freelance : {id}</h1></div>
}
}
export default Profile
Yaaay ! Notre paramètre s'affiche bien. 🎉
Passons maintenant aux choses sérieuses en lançant notre appel API dans la méthode de cycle de vie componentDidMount()
. Encore une fois, nous allons devoir nous passer de notre hook useFetch
puisque nous sommes dans un composant classe.
On commence donc par notre constructor
. Ici, si vous regardez l'API, vous verrez que nous allons récupérer un objet profileData
; il nous faudra donc profileData
dans notre state.
constructor(props) {
super(props)
this.state = {
profileData: {},
}
}
Pour le fetch, vous pouvez réutiliser le code que vous aviez dans useFetch
, version Promise. On le met tout simplement dans componentDidMount()
, ce qui nous donne :
componentDidMount() {
const { id } = this.props
fetch(`http://localhost:8000/freelance?id=${id}`)
.then((response) => response.json())
.then((jsonResponse) => {
this.setState({ profileData: jsonResponse?.freelanceData })
})
}
Et……. Ça fonctionne bien ! 🎉
componentDidMount() {
const { id } = this.props
const fetchData = async () => {
const response = await fetch(`http://localhost:8000/freelance?id=${id}`)
const jsonResponse = await response.json()
if (jsonResponse && jsonResponse.freelanceData) {
this.setState({ profileData: jsonResponse?.freelanceData })
}
}
fetchData()
}
Il ne reste plus qu'à afficher ce qui nous est retourné par l'API. Et voilà notre composant :
import { Component } from 'react'
class Profile extends Component {
constructor(props) {
super(props)
this.state = {
profileData: {},
}
}
componentDidMount() {
const { id } = this.props
fetch(`http://localhost:8000/freelance?id=${id}`)
.then((response) => response.json())
.then((jsonResponse) => {
this.setState({ profileData: jsonResponse?.freelanceData })
})
}
render() {
const { profileData } = this.state
const {
picture,
name,
location,
tjm,
job,
skills,
available,
id,
} = profileData
return (
<div>
<img src={picture} alt={name} height={150} width={150} />
<h1>{name}</h1>
<span>{location}</span>
<h2>{job}</h2>
<div>
{skills &&
skills.map((skill) => (
<div key={`skill-${skill}-${id}`}>{skill}</div>
))}
</div>
<div>{available ? 'Disponible maintenant' : 'Indisponible'}</div>
<span>{tjm} € / jour</span>
</div>
)
}
}
export default Profile
Et voilà ! Vous avez un tout nouveau composant Profile
qui permet d'afficher le profil de vos freelances, et le tout écrit avec un composant classe. 😎Pour l'instant, ce n'est pas stylisé, mais vous trouverez tout sur le style dont vous avez besoin sur le repository GitHub du cours.
Exercez-vous
C'est le moment de mettre en pratique ce que vous avez appris. Vous pouvez commencer l'exercice sur la brancheP4C2-begin
où vous trouverez :
le code que nous avons mis en place dans ce chapitre ;
avec du style ;
ainsi que l'utilisation du Contexte pour récupérer
theme
avec la manière de faire des composants classe.
Cette fois-ci, vous allez convertir le composant classe que nous venons de créer dans pages/Profile/index.jsx
en composant fonction.
Comme toujours, vous trouverez la solution de cet exercice sur la branche P4C2-solution
.
En résumé
Entre le moment où il est monté dans le DOM et le moment où il en est retiré, un composant passe par différentes étapes.
Les méthodes de cycle de vie auxquelles on accède depuis les composants classe permettent d'exécuter notre code à des moments précis qui correspondent à ces étapes.
componentDidMount()
est la méthode privilégiée pour lancer un appel API.
Et voilà ! Vous avez fait le tour (certes rapide) des composants classe. Vous avez maintenant les bases pour évoluer sur une codebase qui comporte des composants classe. Dans le prochain chapitre, vous trouverez quelques conseils pour voler de vos propres ailes dans l'écosystème React. Alors à tout de suite !