# Les bases de React
Pour commencer, je vous recommande fortement de regarder cette vidéo qui expliquera mieux que ce document sur comment fonctionne React : https://www.youtube.com/watch?v=Tn6-PIqc4UM
Ce document fera quand même de son mieux pour expliquer les bases de React et permettra d'expliquer comment intégrer un composant dans le projet.
## Qu'est-ce qu'un composant React ?
Un composant React peut être décrite comme une classe (`class component`) ou une fonction (`functional component`) retournant une description de composant en JSX, un langage permettant de combiner du HTML et du JavaScript. Ces composants ont par convention l'extension de fichier `.jsx` (ou `.tsx` avec TypeScript)
Un composant est principalement constituer de `props` (propriétés) et d'un `state` (état). Cela est universel pour tous les composants.
Voici un basique exemple de composant :
```jsx
function Welcome(props) {
return
Hello, {props.name}
;
}
```
> La règle d'or est que le rendu change lorsqu'un props ou un state change.
Selon comment vous écrivez le composant, classe ou fonctionnelle, la manière de changer les props ou state est différente:
Pour les props :
```tsx
// functional
function Welcome(props) {
return Hello, {props.name}
;
}
// class
class Welcome extends React.Component {
render() {
return Hello, {this.props.name}
;
}
}
```
Pour l'état:
```jsx
// Functionnal
const useTicking = (setDate) => {
React.useEffect(() => {
const timerID = setInterval(() => {
setDate(new Date());
}, 1000);
return () => {
clearInterval(timerID)
}
}, []);
};
export const Clock = (props) => {
const [date, setDate] = React.useState(new Date());
useTicking(setDate);
return (
{ date.toLocaleTimeString() }
);
};
// class
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
{this.state.date.toLocaleTimeString()}
);
}
}
```
Dans ce projet, il est de convention d'écrire en fonctionnel, car cela a pour avantage de fractionner les composants possèdant beaucoup de fonctions (voir par exemple `ContainerOperations.ts`) et de séparer les les propriétés d'états par des `state hooks` (crochet d'états).
La documentation qui suivra utilisera donc l'écriture fonctionnelle. Pour en savoir plus sur l'écriture de classe, vous pouvez essayer [le tutoriel de React](https://reactjs.org/tutorial/tutorial.html).
## Props
Les props sont des données entrer d'un composant. Comme pour un composant html ils décrivent simplement ce que le composant doit représenter.
Exemple :
```tsx
function Welcome(props) {
return Hello, {props.name}
;
}
```
## State vs Stateless
Un composant possédant un état interne utilise `React.setState(newState)` dans un composant de classe ou `React.useState(defaultValue)` dans un composant fonctionnel.
Un composant ne possédant pas d'état est dit `stateless`.
Voici donc un exemple de composant React **avec état** :
```tsx
// Clock.tsx
interface IClockProps {
}
const useTicking = (setTime: React.Dispatch>) => {
React.useEffect(() => {
const timerID = setInterval(() => {
setTime(new Date());
}, 1000);
return () => {
clearInterval(timerID)
}
}, []);
};
export const Clock: React.FC = (props) => {
const [time, setTime] = React.useState(new Date());
useTicking(setTime);
return (
{ time.toLocaleTimeString() }
);
};
```
Et voici la version **sans état** :
```tsx
// Clock.tsx
interface IClockProps {
time: Date
}
export const Clock: React.FC = ({ time }) => {
return (
{ time.toLocaleTimeString() }
);
};
// Parent.tsx
const useTicking = (setTime: React.Dispatch>) => {
React.useEffect(() => {
const timerID = setInterval(() => {
setTime(new Date());
}, 1000);
return () => {
clearInterval(timerID);
};
}, []);
};
export const Parent: React.FC = ({ time }) => {
const [time, setTime] = React.useState(new Date());
useTicking(setTime);
return (
);
};
```
Comme vous pouvez le voir, la différence est que la gestion d'état est donnée au composant parent. Cela permet de réduire les mises à jours de rendu en parallèles et de faire le rendu seulement si l'état du composant parent change.
Vous avez probablement remarqué l'usage de `React.useState()` et `React.useEffect()`. Lorsque l'on utilise une fonction avec le mot clé `use` de React, on utilise ce qu'on appelle un `hook` (crochet).
Il existe plusieurs type de hook et chacun ont leurs propre effet. Dans ce projet, nous utilisont principalement `useState` et `useEffect` mais il y a aucune interdiction pour utiliser d'autres types.
### `useState`
`useState` permet de lier à l'état interne du composant une variable.
La fonction nous fourni 2 paramètres dans une liste. La valeur courante et le setter de cette valeur :
```jsx
const [value, setValue] = React.useState(defaultValue);
```
### `useEffect`
`useEffect` permet de lancer une fonction d'effet lors d'un rendu. Il prend en paramètres :
- une fonction callback d'effet lors du rendu qui retourne lui aussi retourne une fonction d'effet lors de la suppression du rendu.
- Il prend aussi optionnellement un liste de dépendance permettant de déterminer les conditions de rendu
Revenons sur l'exemple de `useTicking`:
```tsx
const useTicking = (setTime) => {
React.useEffect(() => {
// componentDidMount
const timerID = setInterval(() => {
setTime(new Date());
}, 1000);
return () => {
// componentWillUnmount
clearInterval(timerID);
};
}, []);
};
```
Décrivons ce quelle fait :
- La callback de `useEffect` appelle `setInterval` afin d'exécuter une fonction `setTime` toute les seconde.
- Cette callback retourne la fonction de suppression de `setInterval` qui sera exécutée si le composant est disposé.
- `useEffect` possède un tableu de dépendance mais elle est vide. Cela veut dire que la callback sera exécuté qu'une seule est unique fois sur toute la durée de vie du composant
Si on avait enlevé le tableau de dépendance, on aurait eu une boucle infinie ! Car rien n'aurait limité l'exécution de la callback à chaque rendu créé par `setTime`.
> Une règle d'or est qu'il faut mettre un tableau de dépendance lorsque l'on utilise un setteur d'état car il y aura a coup sûr une boucle infinie s'il y en a pas
> Contraposée: Il n'est pas nécessaire de mettre un tableau de dépendances s'il n'y pas de setteur d'état dans la callback
> Il est de convention de mettre les fonctions `useEffect` dans une fonction nommée afin de déterminer ce qu'elle fait. Il est possible d'appeler plusieurs fois `useEffect`, donc il n'est pas dangereux de dissocier les effets.
Si vous avez compris, essayons de créer notre [premier composant React](PremierComposantReact.md).