Voici un exemple complet et corrigé pour créer un hook personnalisé en React qui récupère des données depuis une API, gère les états de chargement, de succès et d'erreur, et permet de traiter dynamiquement plusieurs points de terminaison de l'API.
1. Créer un hook personnalisé useFetch
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Erreur lors de la récupération des données');
}
const result = await response.json();
setData(result);
setError(null);
} catch (err) {
setError(err.message);
setData(null);
} finally {
setLoading(false);
}
};
if (url) {
fetchData();
}
}, [url]);
return { data, loading, error };
}
export default useFetch;
2. Utilisation du hook dans un composant
Voici comment utiliser le hook useFetch
dans un composant React pour récupérer des données depuis l'API et afficher les résultats, ou des messages de chargement et d'erreur.
import React from 'react';
import useFetch from './useFetch'; // Import the custom hook
const DataDisplay = () => {
const url = 'https://jsonplaceholder.typicode.com/posts'; // Example API URL
const { data, loading, error } = useFetch(url);
if (loading) return <p>Chargement...</p>;
if (error) return <p>Erreur: {error}</p>;
return (
<div>
<h1>Liste des Posts</h1>
<ul>
{data && data.map((post) => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</li>
))}
</ul>
</div>
);
};
export default DataDisplay;
test :
import React from 'react';
import DataDisplay from './DataDisplay';
import './App.css';
function App() {
return (
<div className="App">
<h1>Exercice React - Hook Personnalisé</h1>
<DataDisplay />
</div>
);
}
export default App;
et start project :
npm start
Pour gérer différents points de terminaison de l'API de manière dynamique, vous pouvez ajuster l'URL dans votre composant.
import React, { useState } from 'react';
import useFetch from './useFetch';
const DynamicDataDisplay = () => {
const [endpoint, setEndpoint] = useState('posts');
const url = `https://jsonplaceholder.typicode.com/${endpoint}`;
const { data, loading, error } = useFetch(url);
const changeEndpoint = (newEndpoint) => {
setEndpoint(newEndpoint);
};
return (
<div>
<h1>Affichage Dynamique des Données</h1>
<button onClick={() => changeEndpoint('posts')}>Posts</button>
<button onClick={() => changeEndpoint('users')}>Utilisateurs</button>
<button onClick={() => changeEndpoint('comments')}>Commentaires</button>
{loading && <p>Chargement...</p>}
{error && <p>Erreur: {error}</p>}
<ul>
{data && data.map((item) => (
<li key={item.id}>
{item.title ? item.title : item.name} {/* Affiche un titre ou un nom selon les données */}
</li>
))}
</ul>
</div>
);
};
export default DynamicDataDisplay;
test :
import React from 'react';
import './App.css';
import DynamicDataDisplay from './DynamicDataDisplay';
function App() {
return (
<div className="App">
<h1>Exercice React - Hook Personnalisé</h1>
<DynamicDataDisplay />
</div>
);
}
export default App;
et start project :
npm start
pour style App.css :
/* App.css */
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.App {
text-align: center;
padding: 20px;
}
h1 {
color: #333;
font-size: 24px;
}
.data-container {
margin-top: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
ul {
list-style: none;
padding: 0;
max-width: 600px;
margin: 0 auto;
}
li {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 15px;
margin-bottom: 10px;
text-align: left;
}
li h2 {
color: #007bff;
margin: 0;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 15px;
margin: 10px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #0056b3;
}
p {
color: #555;
}
.loading,
.error {
font-size: 18px;
color: #666;
}
Ajouter un commentaire
Veuillez vous connecter pour ajouter un commentaire.
Pas encore de commentaires.