Comment passer de Redux à Recoil

Comme Redux, Recoil est une bibliothèque de gestion d'état dans React. Regardons les différences et comment effectuer le changement lorsque vous êtes prêt.
La gestion d'un état complexe dans React peut parfois être difficile, c'est pourquoi certains d'entre nous utilisent Redux ou des bibliothèques similaires comme MobX pour gérer l'état dans React. [19659003] Recoil est une autre bibliothèque de gestion d'état qui est étroitement modélisée vers l'API Hooks de React. Il vous permet de définir l'état partagé comme atomes et l'état calculé auquel il se réfère en tant que sélecteurs . Si vous voulez en savoir plus sur les limitations auxquelles l'équipe de Facebook a été confrontée et comment ils ont essayé de les résoudre avec recul, vous pouvez regarder cette vidéo .
Une note importante: bien que de nombreuses entreprises, dont Facebook, utilisent Recoil , il est techniquement dans un état expérimental, et son API et ses fonctionnalités peuvent changer.
Dans cet article, je vais vous montrer comment passer de Redux à Recoil et en cours de route comparer les différences. Je vais travailler avec l'exemple TodoMVC du référentiel GitHub de Redux . Vous pouvez télécharger le fichier zip en utilisant ce lien que j'ai créé pour vous 😉. Voici comment fonctionne l'application:
Configuration de Recoil
La première étape pour utiliser une bibliothèque JavaScript est de l'ajouter au projet. Vous pouvez ajouter une référence à l'aide de la balise HTML ou l'installer via npm. Puisque vous avez téléchargé un projet de style npm, installez Recoil en exécutant
npm install recoil
ou yarn add recoil
.
Similaire à l'utilisation de Redux où nous enveloppons notre composant racine avec le [19659010]nous allons le remplacer par
afin que l'état Recoil soit disponible pour les composants enfants.
Ouvrez src / index.js et importez le RecoilRoot
module.
import { RecoilRoot } from "recoil" ;
Puis mettez à jour la fonction de rendu comme suit:
render (
< RecoilRoot >
< App / >
< / RecoilRoot >
document . getElementById ( "root" )
) ;
Définition et mise à jour de l'état
Pour représenter un état, vous déclarez ce qu'on appelle un atome
. Puisque nous voulons stocker une liste de tâches, nous allons créer un atome avec un état par défaut ou initial. Créez un nouveau répertoire recoil et ajoutez un nouveau fichier nommé todos avec le contenu suivant.
import { atom } from [19659016] "recoil" ;
export const todos = atom ( {
clé : "todos"
default : []
} ) ;
Ouvrez maintenant le composant / Header.js et mettez-le à jour avec ce code:
import React from "react" ;
import TodoTextInput de "./ TodoTextInput" ;
import { useSetRecoilState } from "recoil" ;
import { todos } from "../ recoil / todos" ;
const Header = () ) => {
const setTodos = useSetRecoilState ( todos ) ;
const save = ( texte ) => {
if ( text . length ! = = [19659091] 0 ) {
setTodos ( ( todos ) => [
... todos
{
id : Date . now ()
texte
complété : false
}
] ) ;
}
} ;
return [19659014] (
< header className = "header" >
< h1 > todos < / h1 >
< TodoTextInput
nouveauTodo
onSave = { save }
placeholder = "Que faut-il faire?"
/ >
< / header >
) ; [19659031]} ;
export default Header ;
Ce composant affiche une entrée de texte pour collecter de nouveaux todos et les enregistrer. Pour ajouter un nouveau todo, nous avons besoin d'une fonction qui mettra à jour le contenu de l'état todos
. Nous avons utilisé le hook useSetRecoilState ()
pour obtenir une fonction setter qui est utilisée dans la fonction save ()
. À la ligne 11, nous avons utilisé la forme updater de la fonction setter afin de pouvoir créer une nouvelle liste basée sur les anciennes tâches. C'est tout ce que nous devons faire pour être en mesure de collecter et de stocker des éléments à faire.
Si vous comparez cela à Redux, vous devrez créer des créateurs et des réducteurs d'action pour mettre à jour un élément d'état, puis connecter le composant au magasin Redux et expédier les actions. Dans Recoil, vous définissez un atome pour contenir des données, puis utilisez une API hook pour interagir avec ces données. Si vous êtes nouveau dans React et que vous comprenez l'API hooks, il devrait être rapide à saisir Recoil car il est étroitement modélisé à l'API de React, contrairement à Redux où vous auriez besoin de comprendre son style de flux de données unidirectionnel.
Derived State [19659138] La prochaine section de l'application à mettre à jour est le composant
. Il rend une entrée pour marquer toutes les tâches comme terminées, ainsi que deux composants supplémentaires auxquels nous reviendrons plus tard. Alors, ouvrez components / MainSection.js et mettez-le à jour avec le code ci-dessous:
import React from "react" ;
import ] { useRecoilValue useRecoilState } from "recoil" ;
import Footer from "./ Footer ";
import VisibleTodoList from " ../ containers / VisibleTodoList ";
import { completedTodoCount todos } from "../ recoil / todos" ;
const MainSection = () = > {
const completedCount = useRecoilValue ( completedTodoCount ) ;
const [ todoList setTodoList ] = useRecoilState [19659017] ( todos ) ;
const todosCount = todoList . length ;
const clearCompleted = () => {
setTodoList ( ( previousTodos ) =>
previousTodos . filter ( ( todo ) => todo . completed === [19659105] false )
) ;
} ;
const completeAllTodos = () =>
setTodoList ( ( previousTodos ) => {
const areAllMarked = previousTodos . chaque ( ( todo ) => todo . completed ) ;
return previousTodos . carte ( ( todo ) => ( {
... todo
terminé : ! areAllMarked
} ) ) ;
} ) ;
return [19659014] (
< section className = "main" >
{! ! todosCount && (
< span >
< input
className = "tout basculer"
type = "case à cocher"
vérifié = { completedCount === todosCount }
lecture seulement
/ >
< label onClick = { completeAllTodos } / >
< / span >
) }
< VisibleTodoList / >
{! ! todosCount && (
< Pied de page
CompleteCount = { completedCount }
activeCount = { todosCount - completedCount }
onClearCompleted = { clearCompleted }
/ >
) }
< / section > [19659113]) ;
} ;
export default MainSection ;
import React from "react" ;
import ] { useRecoilValue useRecoilState } from "recoil" ;
import Footer from "./ Footer ";
import VisibleTodoList from " ../ containers / VisibleTodoList ";
import { completedTodoCount todos } from "../ recoil / todos" ;
const MainSection = () = > {
const completedCount = useRecoilValue ( completedTodoCount ) ;
const [ todoList setTodoList ] = useRecoilState [19659017] ( todos ) ;
const todosCount = todoList . length ;
const clearCompleted = () => {
setTodoList ( ( previousTodos ) =>
previousTodos . filter ( ( todo ) => todo . completed === [19659105] false )
) ;
} ;
const completeAllTodos = () =>
setTodoList ( ( previousTodos ) => {
const areAllMarked = previousTodos . chaque ( ( todo ) => todo . completed ) ;
return previousTodos . carte ( ( todo ) => ( {
... todo
terminé : ! areAllMarked
} ) ) ;
} ) ;
return [19659014] (
< section className = "main" >
{! ! todosCount && (
< span >
< input
className = "tout basculer"
type = "case à cocher"
vérifié = { completedCount === todosCount }
lecture seulement
/ >
< label onClick = { completeAllTodos } / >
< / span >
) }
< VisibleTodoList / >
{! ! todosCount && (
< Pied de page
CompleteCount = { completedCount }
activeCount = { todosCount - completedCount }
onClearCompleted = { clearCompleted }
/ >
) }
< / section > [19659113]) ;
} ;
export default MainSection ;
Ce que nous avons fait ici, c'est qu'au lieu de nous connecter à Redux et d'appeler mapStateToProps
et mapDispatchToProps
nous avons utilisé deux crochets Recoil, qui sont useRecoilValue
et useRecoilState
. La fonction useRecoilValue ()
est utilisée pour lire le contenu d'un état; dans notre cas, c'est completedTodoCount
. Nous voulons obtenir l'état todos
et également pouvoir le mettre à jour. Pour cela, nous utilisons useRecoilState ()
pour lire todos
et obtenir une fonction pour le mettre à jour. Nous avons deux fonctions, clearCompleted ()
et completeAllTodos ()
qui sont utilisées pour mettre à jour l'état.
Nous devons définir l'état completedTodoCount
. Cela doit être calculé à partir de l'état todos
. Pour cela, nous allons créer ce que l’on appelle le sélecteur dans Recoil. Ouvrez recoil / todos.js et importez le sélecteur du package Recoil.
import { atom selector } from "recoil" ;
Puis définissez le sélecteur comme vous le voyez ci-dessous:
export const completedTodoCount = selector ( {
clé : "completedTodoCount"
get : ( { get } ) => [19659014] {
const list = get ( todos ) ;
return list . réduire (
( count todo ) => ( todo . completed ? compte + 1 : compte )
0
) ;
}
} ) ;
Pour définir un sélecteur, vous appelez la fonction selector ()
avec un objet qui contient le nom de l'état et un get ()
qui calculera et retournera une valeur. Cette fonction reçoit un objet qui a une fonction get ()
qui peut être utilisée pour récupérer des données d'autres atomes ou sélecteurs.
Filtrage de Todos
À ce stade, j'ai couvert la plupart des bases de Recoil et vous pouvez voir en quoi il est différent de Redux mais étroitement modélisé vers l'API Hooks de React. Le reste de cet article ajoutera simplement du code pour rendre l'application pleinement fonctionnelle à l'aide de Recoil.
Le composant suivant sur lequel nous allons travailler est le composant
. Ouvrez containers / FilterLink.js et mettez à jour le fichier avec le code ci-dessous:
import React from "react" ;
import { useRecoilState } de "recoil" ;
import Link from "../ components / Link" ;
import { visibilitéFilter } from "../ recoil / todos" ;
export default ( { filtre enfants } ) => {
const [ visibilité setVisibilityFilter ] = useRecoilState ( visibilitéFilter ) ;
const setFilter = () [19659074] => setVisibilityFilter ( filter ) ;
return (
< Lien
actif = { filtre === visibilité }
setFilter = { setFilter }
enfants = { enfants }
/ >
) ;
} ;
Nous rendons ici le composant qui rendra l'entrée utilisée pour sélectionner comment filtrer les todos qui seront affichés. Nous avons utilisé un nouvel état que nous n’avons pas encore créé, nous allons donc l’ajouter. Ouvrez recoil / todos.js et ajoutez la fonction ci-dessous:
import {
SHOW_ALL
SHOW_COMPLETED
SHOW_ACTIVE
} from "../ constants / TodoFilters" ;
export const visibilitéFilter = atom ] ( {
clé : "visibilitéFilter"
default : SHOW_ALL
} ) ;
Display Todos [19659007] La prochaine chose à faire est d'afficher les todos en fonction du filtre défini. Pour cela, nous allons ajouter un nouveau sélecteur et mettre à jour le composant
. Tant que vous avez encore recoil / todos.js ouvert, ajoutez le sélecteur ci-dessous. export const filteredTodos = selector ( ] {
clé : "filteredTodos"
get : ( { get } ) => [19659014] {
const filter = get ( visibilitéFilter ) ;
const list = get ( todos ) ;
switch ( filter ) {
case SHOW_COMPLETED : [19659427] retour liste . filtre ( ( t ) => t . terminé ) ;
cas SHOW_ACTIVE :
return list . filter ( ( t ) [19659074] => ! t . terminé ) ;
default :
return list ; [19659112]}
} [19659017]
} ) ;
export const filteredTodos = selector ( ] {
clé : "filteredTodos"
get : ( { get } ) => [19659014] {
const filter = get ( visibilitéFilter ) ;
const list = get ( todos ) ;
switch ( filter ) {
case SHOW_COMPLETED : [19659427] retour liste . filtre ( ( t ) => t . terminé ) ;
cas SHOW_ACTIVE :
return list . filter ( ( t ) [19659074] => ! t . terminé ) ;
default :
return list ; [19659112]}
} [19659017]
} ) ;
Open containers / VisibleTodoList.js et mettez à jour le fichier avec le code ci-dessous:
import React from "react" ;
import TodoList from "../ components / TodoList" ;
import { filteredTodos todos } from "../ recoil / todos" ;
import { useRecoilValue useSetRecoilState } from "recoil" ;
const VisibleTodoList = () => {[19659047] const filteredTodoList = useRecoilValue ( filteredTodos ) ;
const setTodos = useSetRecoilate (19659042] useSetRecoilate (19659017) todos ) ;
const completeTodo = [19659014] ( todoId ) => {
setTodos ( ( previousTodos ) =>
previousTodos . carte ( ( todo ) =>
todo . id === todoId ? { ... todo completed : [19659074]! todo . completed } : todo
)
) ;
} ;
const deleteTodo = ( todoId ) => [19659014] {
setTodos ( ( previousTodos ) =>
previousTodos . filter ( ( todo ) => todo . id ! == todoId )
) ;
} ;
const editTodo = ( todoId text ) => {
setTodos ( ( previousTodos ) =>
previousTodos . carte ( ( todo ) =>
todo . id === todoId ? { ... todo text } [19659014]: todo
)
) ;
} ;
return (
< TodoList
filteredTodos = { filteredTodoList }
actions = { { completeTodo deleteTodo editTodo } }
/ > [19659113]) ;
} ;
export default VisibleTodoList ;
Ici, nous avons ajouté trois fonctions pour supprimer un todo, le mettre à jour ou le marquer comme terminé. Nous pouvons considérer ces fonctions comme une combinaison d'actions et de fonctions réductrices dans Redux. J'ai décidé de placer les fonctions dans le même fichier que le composant qui en a besoin, mais vous pouvez les extraire dans un fichier séparé si vous le souhaitez.
À ce stade, nous avons mis à jour l'application pour utiliser Recoil au lieu de Redux. La dernière chose à faire est de mettre à jour components / App.js . Ouvrez ce fichier et modifiez l'instruction d'importation pour les composants
et
.
import Header from "./ Header" ;
import MainSection from "./ MainSection" ;
Et voilà, une application todo mise à jour de l'utilisation de Redux to Recoil.
Conclusion
Déplacer cette application de Redux vers Recoil a été moins compliqué que je ne l’aurais imaginé. Je suppose que ce ne sera pas le cas pour toutes vos applications, en fonction de la façon dont vous avez conçu votre état Redux et de quelques autres facteurs. Mais je pense qu’elle est assez facile à utiliser pour les nouvelles applications, car elle est calquée sur l’API React que vous connaissez bien.
Pour en savoir plus sur Recoil, consultez recoiljs.org . Vous pouvez trouver l'application complète avec le code source sur GitHub .
Source link