
C'est bien beau, nous avons nos composants avec leur state local. Notre panier permet d'ajouter des monsteras, et le total du panier se calcule en fonction.
Mais comment faire pour changer le comportement d'un composant en fonction du state d'un autre composant ?
Par exemple, si je veux ajouter un lien entre mon Cart et mon composant ShoppingList,je peux créer un bouton "Ajouter au panier" dans chaque PlantItem...
Mais comment faire pour venir compléter mon panier en fonction ?
Comme son nom l'indique, un state local... est local. Ni les parents, ni les enfants ne peuvent manipuler le state local d'un composant (ils n'en ont pas la possibilité technique).
Dans ce cas, comment faire pour partager un élément d'état entre plusieurs composants ?
Eh bien, il faudra faire remonter ces données vers le state local du plus proche composant qui est un parent commun, et y garder le state. À partir de là, il sera possible de :
Faire redescendre ces infos avec des props jusqu'aux composants qui en ont besoin.
Faire remonter les demandes d'update toujours dans les props. Pour cela, on peut utiliser la fonction de mise à jour du state récupérée dans useState, en la passant en props aux composants qui en ont besoin.
Où mettre le state ? Dans le composant parent, ou le composant enfant ?
Eh bien, dans la pratique... ça dépend totalement. Il est considéré comme plus propre de garder la logique au maximum dans les composants parents, et que les enfants ne servent qu'à afficher les éléments en props. Mais dans de nombreux cas, il est bien mieux de garder le state dans le composant enfant. Vous apprendrez à le voir avec le temps et l'expérience.
Attaquons-nous donc à notre exemple.
Je commence à faire remonter cart dans App.jsx :
const App = () => {
const [cart, updateCart] = useState(0)
return (
<div>
<Banner>
<img src={logo} alt='La maison jungle' className='lmj-logo' />
<h1 className='lmj-title'>La maison jungle</h1>
</Banner>
<div className='lmj-layout-inner'>
<Cart cart={cart} updateCart={updateCart} />
<ShoppingList cart={cart} updateCart={updateCart} />
</div>
<Footer />
</div>
)
}
export default AppEt toujours dans App.jsx dans le JSX, je passe cart ainsi que updateCart en props :
<Cart cart={cart} updateCart={updateCart} />...que je récupère dans Cart.jsx.
Vous vous souvenez de la déstructuration ? Ça nous permet de récupérer notre prop en une ligne.
J'en profite pour supprimer mon bouton "Ajouter" dans Cart.jsx.
On a donc un panier un peu vide :
const Cart = ({ cart, updateCart }) => {
const monsteraPrice = 8
const [isOpen, setIsOpen] = useState(true)
return isOpen ? (
<div className='lmj-cart'>
<button
className='lmj-cart-toggle-button'
onClick={() => setIsOpen(false)}
>
Fermer
</button>
<h2>Panier</h2>
<h3>Total : {monsteraPrice * cart}€</h3>
<button onClick={() => updateCart(0)}>Vider le panier</button>
</div>
) : (
<div className='lmj-cart-closed'>
<button
className='lmj-cart-toggle-button'
onClick={() => setIsOpen(true)}
>
Ouvrir le Panier
</button>
</div>
)
}
export default CartDu côté de ShoppingList:
Je lui passe updateCart
Puis, je le récupère dans ShoppingList
Je change ensuite ma liste de plantes pour avoir (toujours dans ShoppingList.jsx) :
const ShoppingList = ({ cart, updateCart }) => {
// Petite précision : categories nous vient de la partie
// précédente pour récupérer toutes les catégories uniques de
// plantes.
const categories = plantList.reduce(
(acc, elem) =>
acc.includes(elem.category) ? acc : acc.concat(elem.category),
[]
)
return (
<div className='lmj-shopping-list'>
<ul>
{categories.map((cat) => (
<li key={cat}>{cat}</li>
))}
</ul>
<ul className='lmj-plant-list'>
{plantList.map(({ id, cover, name, water, light }) => (
<div key={id}>
<PlantItem cover={cover} name={name} water={water} light={light} />
<button onClick={() => updateCart(cart + 1)}>Ajouter</button>
</div>
))}
</ul>
</div>
)
}
export default ShoppingListEt voilà ! Maintenant, vous pouvez updater votre panier directement en cliquant sur un bouton lié à chaque plante.
Vous voyez, ce n'est pas si compliqué, il a suffi de :
Faire remonter notre state
Faire descendre le contenu de notre state et la fonction pour l'updater
Déclencher la mise à jour de notre state avec une interaction utilisateur (ici le clic sur le bouton)

Vous allez maintenant pouvoir mettre en application ce que vous avez appris dans ce chapitre sur notre site de plantes.
L'objectif ici est de reprendre notre liste de catégories et de l'améliorer avec le state.
Pour cela, voilà ce que vous allez faire :
Créer un composant à part,Categories, pour gérer les catégories.
Afficher la liste dans un menu déroulant <select />avec des<options />:
chaque catégorie devient une option. Il est possible de choisir une catégorie
à la sélection d'une catégorie, seules les plantes correspondant à la catégorie sélectionnée s'affichent
Créer également un bouton ayant pour label "Réinitialiser". Ce bouton permet de réinitialiser votre state, et d'afficher toutes les catégories de plantes.
Pour utiliser un même état entre plusieurs composants, il faut :
Faire remonter l'état dans le composant parent commun le plus proche.
Puis faire descendre la variable d'état et la fonction pour mettre à jour cet état dans des props.
Dans le chapitre suivant, nous apprendrons à utiliser le hook d'effet pour choisir le moment où nous souhaitons exécuter une action, par exemple pour sauvegarder notre panier dans le localStorage de notre navigateur. Alors, rendez-vous au chapitre suivant.