Aller au contenu

OpenWeatherMap dans un composant React personnalisé

Résumé de l'article

Ce composant « OpenWeatherMap » est conçu pour afficher des données météorologiques. Il utilise l’API Google Maps pour geocoder l’adresse en coordonnées. Ensuite, à l’aide de ces coordonnées, il effectue un appel API à OpenWeatherMap pour récupérer les données météorologiques locales actuelles de cette zone. C’est un composant utile pour quiconque souhaite intégrer rapidement et facilement des données météorologiques basées sur une adresse, en utilisant React dans l’application.

Ce composant « OpenWeatherMap » est conçu pour afficher des données météorologiques. Il utilise l’API Google Maps pour geocoder l’adresse en coordonnées. Ensuite, à l’aide de ces coordonnées, il effectue un appel API à OpenWeatherMap pour récupérer les données météorologiques locales actuelles de cette zone. C’est un composant utile pour quiconque souhaite intégrer rapidement et facilement des données météorologiques basées sur une adresse, en utilisant React dans l’application.

Après l’ajout du composant à la page de détail du compte, un panneau a été ajouté pour afficher un message à l’utilisateur, expliquant qu’une adresse doit être fournie pour afficher les informations météorologiques du compte. Il ne sera visible que lorsque la ville, la province ou l’État et le pays ne sont pas complétés.

Vous devez avoir votre propre compte, afin d’obtenir une clé API à insérer dans le code fourni dans ce document.

Commencez par créer un nouveau module. Dans cet exemple, il s’appelle « OpenWeatherMap ». Ensuite, copiez son module ID, car il sera utilisé à l’étape 3. Cela se fait simplement en cliquant dessus, dans la section supérieure de la page du module.

2. Créer un aggregate « temporary » (il pourra être supprimé après la création de l’entity, à l’étape 3)

Section intitulée « 2. Créer un aggregate « temporary » (il pourra être supprimé après la création de l’entity, à l’étape 3) »

3. Ajouter une Entity et des attributs pour le composant météo

Section intitulée « 3. Ajouter une Entity et des attributs pour le composant météo »

Créez une Entity « OpenWeatherMap » sous l’Aggregate temporaire. Depuis le properties panel, définissez le base type sur « component ». Ensuite, ajoutez un attribut de type text (string), mettez « moduleId » comme nom et collez la valeur de module copiée à l’étape 1.

À partir de ce moment, le composant réutilisable « Google Maps » sera dans la toolbox, mais ne fonctionnera pas tant que le code Javascript n’aura pas été ajouté.

4. Copier et insérer le code JavaScript pour les appels API

Section intitulée « 4. Copier et insérer le code JavaScript pour les appels API »

Pour ajouter le code Javascript, copiez et collez ce code dans le module nouvellement créé (de l’étape 1) et enregistrez la modification. Pour en savoir plus sur ce que fait chaque section du code, consultez la dernière section de ce guide.

Insérez une clé Google à la ligne 35 et une clé OpenWeatherMap à la ligne 56

import React, { useState, useEffect } from "react";
import Box from "@esm/components/web/Box";
function formatDateInFrench(date) {
const options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' };
return date.toLocaleDateString('fr-FR', options);
};
// Cette fonction prend le code météo et renvoie le nom de classe de l'icône Weather Icons appropriée
function getWeatherIcon(code, isNight) {
switch (code) {
case '01d':
return isNight ? 'wi-night-clear' : 'wi-day-sunny';
case '01n':
return 'wi-night-clear';
case '09d':
case '09n':
case '10d':
case '10n':
return 'wi-rain';
case '13d':
case '13n':
return 'wi-snow';
case '03d':
case '03n':
case '04d':
case '04n':
return 'wi-cloudy';
default:
return 'wi-na';
}
}
function getAddressCoordinates(address) {
return fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`)
.then(response => response.json())
.then(data => {
if (data.results && data.results.length > 0) {
const location = data.results[0].geometry.location;
return {
latitude: location.lat,
longitude: location.lng,
};
} else {
throw new Error('Unable to geocode address.');
}
});
}
const OpenWeatherMap = ({ data, ...props }) => {
const [weatherData, setWeatherData] = useState(null);
useEffect(() => {
getAddressCoordinates(data.address)
.then(coords => {
return fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${coords.latitude}&lon=${coords.longitude}&lang=fr&appid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`);
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => setWeatherData(data))
.catch(error => {
console.error('There has been a problem:', error);
});
}, [data.address]);
if (!weatherData) return <div>Loading...</div>;
// Conversion de Kelvin à Celsius
const tempCelsius = Math.round(weatherData.main.temp - 273.15);
//weatherData.dt
// Obtenez le code météo pour déterminer l'icône appropriée
const weatherIcon = getWeatherIcon(weatherData.weather[0].icon, isNight(weatherData.weather[0].icon));
// Fonction pour vérifier si le code météo indique la nuit
function isNight(iconCode) {
return iconCode.includes('n');
}
const dateToday = new Date();
const dateT = formatDateInFrench(dateToday);
const description = weatherData.weather[0].description;
const capitalizedDescription = description.charAt(0).toUpperCase() + description.slice(1).toLowerCase();
const styles = {
weatherBox: {
padding: '10px 20px 20px 20px',
height: '100%',
width: '100%'
},
nowText: {
whiteSpace: 'pre- wrap',
fontWeight: '600',
fontSize: '16px'
},
temp: {
fontWeight: '800',
fontSize: '50px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
textColor: '#808080',
color: '#808080',
},
tempIcon: {
paddingRight: '20px',
},
description: {
borderBottom: 'solid 0.1px',
borderColor: '#D3D3D3',
textColor: '#808080',
fontWeight: '400',
fontSize: '1rem',
paddingBottom: '5px'
},
location: {
justifyContent: 'center',
paddingTop: '5px',
paddingBottom: '3px'
},
}
return (
<Box {...props}>
<div className='widget' style={styles.weatherBox}>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css" />
<div>
<span style={styles.nowText}>Maintenant</span>
<div style={styles.temp}>
{tempCelsius}°C {weatherIcon && <i className={`wi ${weatherIcon}`} style={styles.tempIcon}></i>}
</div>
<h3 style={styles.description}>{capitalizedDescription}</h3>
</div>
Vent: {weatherData.wind.speed}m/s
Humidité: {weatherData.main.humidity}%
<div style={styles.location}>
<i className="fal fa-calendar"></i> {dateT}
</div>
<div style={styles.location}>
<i className="far fa-map-marker-alt"></i> {data.address}
</div>
</div>
</Box>
);
};
export default OpenWeatherMap;

5. Ajouter des composants d’interface utilisateur pour afficher la météo et les messages

Section intitulée « 5. Ajouter des composants d’interface utilisateur pour afficher la météo et les messages »

Glissez-déposez le composant OpenWeatherMap de la toolbox vers l’interface utilisateur de votre page. Ensuite, copiez le style appliqué au main information field panel et collez-le au composant nouvellement ajouté.

6. Exécuter une commande pour modifier l’adresse

Section intitulée « 6. Exécuter une commande pour modifier l’adresse »

Ajoutez un comportement « execute a command » à OpenWeatherMap, onClick, modify et liez-le à la commande correspondante permettant aux utilisateurs de changer l’adresse du compte. À partir de ce moment, le composant météo est entièrement fonctionnel.

Vous auriez pu décider de gérer cela via le code en changeant la ligne 70 pour ces deux lignes de code. La première ligne validera si l’adresse du compte est inexistante et la deuxième vérifie que les coordonnées GPS ne sont pas disponibles après l’appel API de la fonction getAddressCoordinates.

if (!data.adress) return <div>Aucune adresse existante</div>;
if (!weatherData) return <div>Loading...</div>;

7. Ajouter un comportement Show/Hide selon les champs d’adresse

Section intitulée « 7. Ajouter un comportement Show/Hide selon les champs d’adresse »

Pour fournir des informations météorologiques précises, un utilisateur devra fournir la ville, la province ou l’État et le pays. Ajoutons un comportement « show/hide component based on a condition » à OpenWeatherMap.

8. Créer un message utilisateur pour une adresse manquante

Section intitulée « 8. Créer un message utilisateur pour une adresse manquante »

Pour créer un message informant l’utilisateur que la WeatherMap ne peut pas être affichée en raison d’un manque de données, glissez-déposez un composant text dans le contenu de la page et changez son label pour le message souhaité. Ensuite, ajoutez un autre composant text, placé sous le premier, et changez le texte pour « Click here to edit ». Changez sa couleur en bleu et soulignez-le, puis appliquez un align right. Ensuite, ajoutez une icône à gauche du premier message. Dans cet exemple, l’icône « thunderstorm sun » a été utilisée. Un item spacing a été ajouté à la boîte contenant l’icône et le composant text. Copiez le style du main field panel et collez-le au nouveau. Enfin, appliquez un item spacing à la boîte principale pour laisser de l’espace entre les 2 field panels.

Ajoutez un comportement « execute a command » au deuxième composant text, pour permettre aux utilisateurs d’ajouter l’adresse du compte.

Enfin, pour masquer cette boîte lorsque les 3 champs contiennent des données, ajoutez ce « show/hide component based on a condition » :

Name: City / Operator: Equal / Value (JS): null

Name: State or Province / Operator: Equal / Value (JS): null

Name: Country / Operator: Equal / Value (JS): null

Informations importantes

  • Les hooks `useState` et `useEffect` sont importés de React. Ces hooks permettent respectivement de gérer l’état local du composant ainsi que d’exécuter les effets de bord. Dans ce cas, si l’adresse du compte devait être modifiée, le changement s’appliquerait automatiquement et afficherait les données météorologiques en conséquence.

  • Le composant `Box` est importé pour fournir une mise en page standard.

Composants OpenWeatherMap :

`formatDateInFrench(date)` : Cette fonctionnalité utilise une date comme argument et la convertit au format de date français, renvoyant une chaîne formatée.

function formatDateInFrench(date) {
const options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' };

`getWeatherIcon(code, isNight)` : Cette fonctionnalité renvoie le nom de classe approprié pour Weather Icons, selon le code d’icône météo (par exemple, ‘01d’ pour une journée ensoleillée) et qu’il s’agisse du jour ou de la nuit.

function getWeatherIcon(code, isNight) {
switch (code) {
case '01d':
return isNight ? 'wi-night-clear' : 'wi-day-sunny';
case '01n':
return 'wi-night-clear';
case '09d':
case '09n':
case '10d':
case '10n':
return 'wi-rain';
case '13d':
case '13n':
return 'wi-snow';
case '03d':
case '03n':
case '04d':
case '04n':
return 'wi-cloudy';
default:
return 'wi-na';
}
}

`getAddressCoordinates(address)` : Cette fonctionnalité utilise l’API Google Maps pour convertir une adresse en coordonnées de longitude et latitude.

function getAddressCoordinates(address) {
return fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=XXXXXXXXXXXXXXXXX`)
.then(response => response.json())
.then(data => {
if (data.results && data.results.length > 0) {
const location = data.results[0].geometry.location;
return {
latitude: location.lat,
longitude: location.lng,
};
} else {
throw new Error('Unable to geocode address.');
}
});
}

**useState** : Est utilisé pour générer l’état local du composant et stocker les données météorologiques obtenues via l’API.

**useEffect** : au sein de ce composant, le code :

1. Geocode l’adresse fournie.

2. Utilise les coordonnées pour interroger l’API OpenWeatherMap.

3. Les données météorologiques sont ensuite stockées dans l’état local du composant, comme mentionné ci-dessus.

useEffect(() => {
getAddressCoordinates(data.address)
.then(coords => {
return fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${coords.latitude}&lon=${coords.longitude}&lang=xxxxxxxxxxxxxxxxxxxxxxx`);
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => setWeatherData(data))
.catch(error => {
console.error('There has been a problem:', error);
});
}, [data.address]);

**Affichage** : si les données météorologiques ne sont pas encore affichées, le composant affichera « Loading… ». Sinon, il affichera les informations météorologiques, incluant la température, l’icône météo, l’humidité, la date, etc. Les styles appliqués ici sont des constantes déclarées et assignées dans la section Style, vue ci-dessous.

return (
<Box {...props}>
<div className='widget' style={styles.weatherBox}>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css" />
<div>
<span style={styles.nowText}>Maintenant</span>
<div style={styles.temp}>
{tempCelsius}°C {weatherIcon && <i className={`wi ${weatherIcon}`} style={styles.tempIcon}></i>}
</div>
<h3 style={styles.description}>{capitalizedDescription}</h3>
</div>
Vent: {weatherData.wind.speed}m/s
Humidité: {weatherData.main.humidity}%
<div style={styles.location}>
<i className="fal fa-calendar"></i> {dateT}
</div>
<div style={styles.location}>
<i className="far fa-map-marker-alt"></i> {data.address}
</div>
</div>
</Box>
);
};

**Styles** : Un objet `styles` a été ajouté à l’intérieur du composant pour appliquer des styles CSS aux différentes parties du widget météo.

const styles = {
weatherBox: {
padding: '10px 20px 20px 20px',
height: '100%',
width: '100%'
},
nowText: {
whiteSpace: 'pre- wrap',
fontWeight: '600',
fontSize: '16px'
},
temp: {
fontWeight: '800',
fontSize: '50px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
textColor: '#808080',
color: '#808080',
},
tempIcon: {
paddingRight: '20px',
},
description: {
borderBottom: 'solid 0.1px',
borderColor: '#D3D3D3',
textColor: '#808080',
fontWeight: '400',
fontSize: '1rem',
paddingBottom: '5px'
},
location: {
justifyContent: 'center',
paddingTop: '5px',
paddingBottom: '3px'
},
}

Ce guide explique comment créer et intégrer un composant OpenWeatherMap dans une application React personnalisée. Il décrit la configuration du module, l’ajout des API requises et la gestion des interactions utilisateur pour afficher les données météorologiques en fonction de l’adresse fournie.