Sous Windows, pour savoir quel processus utilise un port, lancez la commande Get-Process
dans Powershell :
Exemple pour le port 5433
:
Get-Process -Id (Get-NetTCPConnection -LocalPort 5433).OwningProcess
Publié le :
Sous Windows, pour savoir quel processus utilise un port, lancez la commande Get-Process
dans Powershell :
Exemple pour le port 5433
:
Get-Process -Id (Get-NetTCPConnection -LocalPort 5433).OwningProcess
Publié le :
Voici un modèle de composant React minimal :
// MyComponent.tsx
import React, { ReactNode } from 'react';
import styles from "./MyComponent.module.scss";
interface Props {
children: ReactNode;
notRequiredProperty?: string;
}
export const MyComponent: React.FC = ({ children, notRequiredProperty }: Props) => {
return <div className={styles.myComponentClass}>{children}< /div>;
};
Explications :
<MyComponent children={<p>EXAMPLE</p>} />
MyComponent.module.scss
, dans lequel se trouve une règle CSS pour la
classe myComponentClass
.children
.Props
pour définir les propriétés du composant. Cela facilite l’autocomplétion et
permet la validation du typage à la compilation.notRequiredProperty
est facultative lorsqu’on appelle le composant.Si on souhaite créer un wrapper pour un composant existant, on veut souvent qu’il accepte les mêmes propriétés. Dans ce cas, on peut déclarer l’interface et le composant ainsi :
type Props = SomeComponentToWrapProps & {
extraProperty1: string
};
export const MyComponent: React.FC = ({ extraProperty1, inheritedProp1, ...others }: Props) => {
// [...]
};
Explications :
SomeComponentToWrapProps
, avec celle déclarée ici.others
.Publié le :
Contrairement à Angular, React propose peu de solutions par défaut aux problèmes les plus courants. Il faut souvent ajouter des modules en dépendance, et il est parfois difficile de ne pas se perdre dans la jungle des modules pour React.
Voici une liste de modules et de pratiques utiles pour les besoins courants.
On peut initialiser facilement un projet React avec l’outil CRA
(Create React App).
Il crée l’arborescence de base, via une simple commande comme npx create-react-app my-app --template typescript
.
Le module react-router fait ça très bien.
Pour récupérer des données auprès d’une API ou via d’autres méthodes asynchrones, on peut utiliser SWR ou react-query.
Si on souhaite gérer un état globale de l’application au niveau local, on peut utiliser redux avec redux-toolkit ou alors recoil.
Le module react-hook-form fait ça très bien. Il supporte notamment Yup pour gérer la validation de champs.
Le module react-i18next permet de gérer une appli multilingue.
Pour restreindre des classes CSS à un composant en particulier, on peut utiliser le concept de modules CSS.
Les principales bibliothèques graphiques sont disponibles pour React, et notamment Material UI. Elle fonctionne très bien, sauf avec le hook-form. C’est problématique et cela nécessite de recréer un composant « Contrôlable », pour chaque type de champ de formulaire.
Plusieurs bibliothèques pour les tests fonctionnent bien avec React, notamment jest.
On peut combiner prettier et eslint, pour normaliser la base de code. Il existe des extensions à eslint spécialement pour React, afin de détecter et remonter si certaines mauvaises pratiques sont utilisées.
Pour documenter et présenter une bibliothèque de composants, on peut utiliser Storybook. Cela permet de manipuler et tester chaque composant, dans une interface dédiée.
Pour utiliser plus facilement la base de données locale IndexedDB, on peut y accéder via dexie.
Pour extraire les données d’un jeton JWT, on peut utiliser jwt-decode.
Publié le :
Régulièrement en Javascript, on veut écouter les changements sur un élément, mais ne les prendre en compte qu’à
intervalle régulier.
Par exemple, si on écoute le déplacement de la souris pour lancer un traitement, on n’a pas besoin de l’exécuter
à chaque changement de position, mais uniquement tous les 300 ou 500ms.
Pour éviter l’effet « rebond », on utilise alors une fonction de debounce, ou dans React, un hook.
import { useEffect, useState } from 'react';
/**
* Delays the value change, so it’s only committed once during the specified duration.
*
* Usage :
* <pre>
* const debouncedValue = useDebouncedValue(realTimeValue, 500);
* <pre>
*/
export const useDebouncedValue = <T>(input: T, duration = 500): T => {
const [debouncedValue, setDebouncedValue] = useState(input);
useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedValue(input);
}, duration);
return () => {
clearTimeout(timeout);
};
}, [input, duration]);
return debouncedValue;
};
On veut afficher un message dans la console au changement de valeur du champ de formulaire,
mais limiter ce traitement avec un debounce.
import React, { useEffect, useState } from 'react';
import { useDebouncedValue } from './utils/debounce';
export default (() => {
const [myValue, setMyValue] = useState('');
const myDebouncedValue = useDebouncedValue(myValue, 500);
useEffect(() => {
console.log('This log is displayed when the value of debouncedFilterNom changes', myDebouncedValue);
}, [myDebouncedValue]);
const handleValueChange = async (event: any) => {
setMyValue(event.target.value);
};
return (
<form>
<input type="text" onChange={handleValueChange} value={myValue} />
</form>
);
}) as React.FC;
Publié le :
Voici une fonction pour construire une queryString à partir d’un objet.
Version JavaScript :
export const buildQueryString = (parameters) => {
const paramParts = Object.entries(parameters)
.map(([key, value]) => `${key}=${encodeURI(value)}`);
return paramParts.length > 0 ? `?${paramParts.join('&')}` : '';
};
Version TypeScript :
export const buildQueryString = (parameters: { [key: string]: string }) => {
const paramParts = Object.entries(parameters)
.map(([key, value]) => `${key}=${encodeURI(value)}`);
return paramParts.length > 0 ? `?${paramParts.join('&')}` : '';
};
Explications :
&
et ?
est ajouté en préfixe de la chaîne.Publié le :
Il est possible de modifier l’auteur de tous les anciens commits d’un dépôt Git.
Pour cela, utilisez la commande suivante, après l’avoir personnalisée selon vos besoins :
git filter-branch --env-filter '
WRONG_EMAIL="wrong@email.com"
NEW_NAME="John Doe"
NEW_EMAIL="j.doe@email.com"
if [ "$GIT_COMMITTER_EMAIL" = "$WRONG_EMAIL" ]
then
export GIT_COMMITTER_NAME="$NEW_NAME"
export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$WRONG_EMAIL" ]
then
export GIT_AUTHOR_NAME="$NEW_NAME"
export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
Explications :
On indique l’adresse email utilisée par tous les commits que l’on souhaite modifier, ainsi que le nom d’utilisateur et l’adresse email correcte que l’on souhaite utiliser à la place.
Publié le :
Sous Linux, l’utilitaire ncdu (pour NCurses Disk Usage) permet de trouver quel fichier ou répertoire vous bouffe tout votre espace disque.
Il est disponible sur les dépôts officiels Debian et Ubuntu et donc facile à installer.
sudo apt install ncdu
ncdu
Note : ncdu a été réécrit dans une v2 encore récente. Selon la version des dépôts, c’est peut-être la v1 qui sera installée.
Publié le :
Dans une application ou un site web, on peut stocker des informations dans le navigateur de l'utilisateur, pour un nom de domaine spécifique.
Deux approches principales : les cookies et le Storage
. Pour la seconde, deux possibilités :
sessionStorage
ou localStorage
.
La principale différence, c'est que les cookies sont accessibles côté client et côté serveur.
À l'inverse, il n'y a aucun moyen côté serveur d'accéder au contenu ni du localStorage
ni du sessionStorage
.
Remarque :
Quand on parle de "sessions" pour le sessionStorage
, il n'y a aucun rapport avec les sessions
entre client/serveur comme on peut les manipuler en PHP, par exemple.
Les données stockées en sessionStorage sont rattachées à un onglet.
Si on recharge la page au sein d'un même onglet, les données sont conservées.
En revanche, elles expirent à sa fermeture.
Les données stockées en sessionStorage sont rattachées à un onglet.
Remarque :
Selon le navigateur, si on restaure un onglet fermé précédemment, on récupère le sessionStorage
tel qu'il était avant fermeture. C'est le comportement pour les navigateurs basés sur Chrome.
De même, si on duplique un onglet ouvert, la copie hérite d'une copie du sessionStorage
de l'onglet original.
Publié le :
Pour faire du refactoring automatique en PHP, on peut utiliser son IDE ou la lib Rector (installable via Composer).
Elle permet notamment d'automatiser la migration de code PHP vers une version plus récente de PHP.
Quelques exemples :
??
et ?:
Il est également possible de créer ses propres règles de refactoring.
Grafikart a sorti une vidéo de présentation de l'outil.
Publié le :
Si vous construisez des APK Android avec Cordova, vous pouvez rencontrer ce genre d'erreur :
[...]
> Task :app:preReleaseBuild FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all files for configuration ':app:releaseRuntimeClasspath'.
> Could not resolve com.android.support:support-v4:27.+.
Required by:
project :app
> Failed to list versions for com.android.support:support-v4.
> Unable to load Maven meta-data from https://jcenter.bintray.com/com/android/support/support-v4/maven-metadata.xml.
> Could not get resource 'https://jcenter.bintray.com/com/android/support/support-v4/maven-metadata.xml'.
> Could not GET 'https://jcenter.bintray.com/com/android/support/support-v4/maven-metadata.xml'.
> Read timed out
[...]
Cela est dû à la coupure du dépôt jcenter.
La solution pour le remplacer est décrite dans plein de tickets sur StakOverflow (ex: Question #67418153).
En bref : il faut modifier le fichier build.gradle
.
Malheureusement, vous n'avez peut-être pas accès à ce fichier, si c'est une Plateforme d'Intégration Continue qui se charge du build.
Dans ce cas, ce fichier n'est probablement pas versionné, mais générée automatiquement dans un répertoire nommé platforms/
.
Entre chaque build, veillez à bien supprimer ce répertoire platforms/
.
Ainsi, le fichier build.gradle
sera régénéré en utilisant des dépôts corrects.