React Native
...
Data objects
Guide technique : CRUD avec GraphQL et Relay sur React Native
17 min
tutoriel crud graphql avec react native introduction gérer les données sur back4app en utilisant graphql est une option puissante pour tout type d'application, accélérant les requêtes et simplifiant les plus complexes back4app utilise des conventions communes pour la configuration de graphql et fournit d'excellents outils pour vous aider à configurer votre environnement de développement dans ce guide, vous apprendrez à effectuer des opérations de données de base à travers un exemple d'application crud, qui vous montrera comment créer, lire, mettre à jour et supprimer des données de votre base de données de serveur parse dans react native en utilisant graphql et relay vous allez d'abord créer vos fonctions de composant pour chaque opération crud, en les utilisant plus tard dans une mise en page d'écran complète, résultant en une application de liste de tâches à tout moment, vous pouvez accéder à ce projet via nos dépôts github pour consulter les styles et le code complet dépôt d'exemple javascript prérequis pour ce tutoriel, nous utiliserons le serveur parse en version 4 4 si vous souhaitez utiliser d'autres versions, vous pouvez consulter le code de mutation correspondant à https //www back4app com/docs/parse graphql/graphql logout mutation exemple pour votre version respective une application react native créée et connectée à back4app ; concluez le tutoriel de configuration de l'environnement relay bonne compréhension de relay store et relay connection updater ; vous pouvez en lire plus sur documentation relay modern nous utiliserons javascript comme implémentation par défaut objectif construire une application crud de base en react native en utilisant parse, graphql et relay 1 création de la classe todo dans cette première étape, nous devons définir la classe avec laquelle l'application va fonctionner la todo todo classe doit seulement avoir un champ titre( string string ) décrivant la tâche et un champ done( boolean boolean ) indiquant si la tâche est terminée vous pouvez utiliser une mutation générique pour créer la classe dans votre base de données si vous ne l'avez pas, en suivant notre guide dans le graphql cookbook https //www back4app com/docs/parse graphql/graphql mutation create object vous pouvez également créer la classe en utilisant le tableau de bord de back4app, via le navigateur de base de données lui même ou depuis les consoles js ou graphql après avoir créé cette nouvelle classe, n'oubliez pas de télécharger le schema json schema json fichier depuis le tableau de bord et de le sauvegarder dans votre application à l'intérieur du data data répertoire cela est nécessaire pour que le relay compiler génère automatiquement les types à partir des requêtes, mutations, etc à ce stade, votre tableau de bord back4app aura automatiquement généré des mutations crud pour l'objet de classe, pour les voir vous pouvez aller à la console graphql, ouvrir l'onglet docs et rechercher todo todo 2 interroger et rendre les objets créons maintenant un composant qui sera responsable de faire la requête de la liste sur le serveur back4app, d'établir une connexion pour les objets, et de rendre et mettre à jour automatiquement le contenu de la liste au fur et à mesure qu'il change créez un nouveau fichier nommé todolistqueryrenderer js todolistqueryrenderer js dans votre src src répertoire avec le code suivant 1 import react from 'react'; 2 import { view, text } from 'react native'; 3 import { graphql, queryrenderer } from 'react relay'; 4	 5 // prerequisite properly configured relay environment 6 import environment from ' / /relay/environment'; 7	 8 // this will be created in the next steps 9 import todolist from ' /todolist'; 10	 11 const todolistqueryrenderer = () => { 12 return ( 13 // the queryrenderer acts as a wrapper to any code, providing query results to 14 // the child components and updating them as needed 15 // note that the query is using a fragment called todolist query, 16 // which will be created in the next steps 17 \<queryrenderer 18 environment={environment} 19 query={graphql` 20 query todolistqueryrendererquery { 21 todolist query 22 } 23 `} 24 variables={null} 25 render={({ error, props }) => { 26 if (error) { 27 return ( 28 \<view> 29 \<text>{error message}\</text> 30 \</view> 31 ); 32 } else if (props) { 33 return \<todolist query={props} />; 34 } 35 return ( 36 \<view> 37 \<text>loading \</text> 38 \</view> 39 ); 40 }} 41 /> 42 ); 43 } 44	 45 export default todolistqueryrenderer; 3 créer le composant liste et fragment d'objet créons maintenant notre composant de liste, qui affichera les données récupérées depuis le queryrenderer le composant contiendra pour l'instant uniquement une simple vue défilante contenant une fonction de mappage rendant chaque nœud allez y et créez un nouveau fichier dans votre répertoire src appelé todolist js todolist js et ajoutez le code suivant 1 import react, {usestate} from 'react'; 2 import { 3 view, 4 safeareaview, 5 image, 6 scrollview, 7 statusbar, 8 stylesheet, 9 touchableopacity, 10 } from 'react native'; 11	 12 import { 13 list, 14 text as papertext, 15 button as paperbutton, 16 textinput as papertextinput, 17 } from 'react native paper'; 18 import {createfragmentcontainer} from 'react relay'; 19	 20 const todolist = props => { 21 const \[newtodotitle, setnewtodotitle] = usestate(''); 22	 23 const {query} = props; 24 const {todos} = query; 25	 26 const rendertodos = () => { 27 if (!todos) { 28 return null; 29 } 30	 31 return todos edges map(({node todo}) => ( 32 \<list item 33 key={todo id} 34 title={todo title} 35 titlestyle={todo done ? styles todo text done styles todo text} 36 style={styles todo item} 37 right={props => ( 38 <> 39 {!todo done && ( 40 \<touchableopacity onpress={() => updatetodo(todo id, true)}> 41 \<list icon { props} icon="check" color={'#4caf50'} /> 42 \</touchableopacity> 43 )} 44	 45 \<touchableopacity onpress={() => deletetodo(todo id)}> 46 \<list icon { props} icon="close" color={'#ef5350'} /> 47 \</touchableopacity> 48 \</> 49 )} 50 /> 51 )); 52 }; 53	 54 return ( 55 <> 56 \<statusbar backgroundcolor="#208aec" /> 57 \<safeareaview style={styles container}> 58 \<view style={styles header}> 59 \<papertext style={styles header text bold}> 60 {'react native on back4app'} 61 \</papertext> 62 \<papertext style={styles header text}>{'product creation'}\</papertext> 63 \</view> 64 \<view style={styles create todo container}> 65 \</view> 66 \<scrollview style={styles todo list}>{rendertodos()}\</scrollview> 67 \</safeareaview> 68 \</> 69 ); 70 }; 71	 72 const todolistfragmentcontainer = createfragmentcontainer(todolist, { 73 query graphql` 74 fragment todolist query on query { 75 todos(first 50) @connection(key "todolist todos", filters \[]) { 76 edges { 77 node { 78 id 79 title 80 done 81 } 82 } 83 } 84 } 85 `, 86 }); le query renderer à l'étape 2 attend un fragment de données nommé todolist query todolist query , donc nous l'avons également ajouté au composant de liste à la fin du fichier n'oubliez pas que les fragments graphql sont des structures responsables de l'appel des données dont les composants ont besoin pour se rendre et de spécifier ce qui doit être retourné 4 création des objets la première étape pour gérer vos données dans votre base de données graphql back4app est d'en avoir nous devons créer une fonction à appeler pour créer un nouveau todo todo dans notre composant de liste en utilisant une mutation responsable de cela commençons par la mutation, donc créez un nouveau fichier nommé createtodomutation js createtodomutation js dans le src/mutations src/mutations répertoire contenant le code suivant 1 import { commitmutation, graphql } from "react relay"; 2 import { root id, connectionhandler } from 'relay runtime'; 3	 4 const connectioncreateedgeupdater = (store, nodeid) => { 5 const parentproxy = store get(root id); 6 const todoconnection = connectionhandler getconnection(parentproxy, 'todolist todos'); 7	 8 const newtodo = store get(nodeid); 9 const edge = connectionhandler createedge(store, todoconnection, newtodo, 'todoedge'); 10 11 // no cursor provided, append the edge at the end 12 connectionhandler insertedgeafter(todoconnection, edge); 13 } 14	 15 const mutation = graphql` 16 mutation createtodomutation($input createtodoinput!) { 17 createtodo(input $input) { 18 todo { 19 id 20 title 21 done 22 } 23 } 24 } 25 `; 26	 27 function commit({ environment, input, oncompleted, onerror }) { 28 const variables = { input }; 29	 30 commitmutation(environment, { 31 mutation, 32 variables, 33 oncompleted, 34 onerror, 35 updater (store) => { 36 const todoid = store getrootfield('createtodo') getlinkedrecord('todo') getvalue('id'); 37	 38 connectioncreateedgeupdater(store, todoid) 39 } 40 }); 41 } relay modern nous fournit un ensemble de points de terminaison api à utiliser pour mettre à jour les données après les appels de mutation dans cette fonction, nous avons utilisé certaines de ses fonctions pour obtenir le nouveau todo todo créé et mettre à jour la liste déjà existante sur le frontend avec cette approche, nous évitons un nouvel appel au backend, économisant ainsi le temps qui serait dépensé pour une nouvelle requête, la connexion internet de l'utilisateur, le surchargement de données, et plus encore ajoutez maintenant la fonction suivante au todolist todolist composant, qui appellera le createtodomutation createtodomutation et sera référencé plus tard par un bouton 1 const createtodo = () => { 2 const input = { 3 fields { 4 title newtodotitle, 5 done false, 6 }, 7 }; 8	 9 createtodomutation commit({ 10 environment, 11 input input, 12 oncompleted () => { 13 alert alert('success!', 'todo created!'); 14 setnewtodotitle(''); 15 }, 16 onerror (errors) => { 17 alert alert('error!', errors); 18 }, 19 }); 20 } 5 mise à jour des objets mettre à jour un objet est similaire à le créer, avec l'ajout que, lorsque vous mettez à jour un objet en utilisant relay modern, vous devez simplement demander les champs que vous souhaitez mettre à jour avec le nouvel état sur la sortie de la mutation créez un nouveau fichier nommé updatetodomutation js updatetodomutation js dans le src/mutations src/mutations répertoire contenant le code suivant 1 import { commitmutation, graphql } from "react relay"; 2	 3 const mutation = graphql` 4 mutation updatetodomutation($input updatetodoinput!) { 5 updatetodo(input $input) { 6 todo { 7 id 8 title 9 done 10 } 11 } 12 } 13 `; 14	 15 function commit({ environment, input, oncompleted, onerror }) { 16 const variables = { input }; 17	 18 commitmutation(environment, { 19 mutation, 20 variables, 21 oncompleted, 22 onerror, 23 }); 24 } 25	 26 export default { 27 commit, 28 }; tout comme dans l'étape précédente, ajoutez la fonction suivante au todolist todolist composant, qui appellera le updatetodomutation updatetodomutation et sera référencé plus tard par un bouton 1 const updatetodo = (todoid, done) => { 2 const input = { 3 id todoid, 4 fields { 5 done, 6 } 7 } 8	 9 updatetodomutation commit({ 10 environment, 11 input input, 12 oncompleted () => { 13 alert alert('success!', 'todo updated!'); 14 }, 15 onerror (errors) => { 16 alert alert('error!', errors); 17 }, 18 }); 19 } 6 suppression des objets lorsque vous supprimez un objet, avec les api relay store, vous pouvez mettre à jour la liste et retirer l'ancien objet de l'interface nous allons appeler un rappel de mise à jour, similaire à la mise à jour de createtodo createtodo , mais nous passerons la connexion et l'identifiant de la tâche à supprimer de la liste de cette manière, nous gardons l'interface fidèlement mise à jour par rapport à notre serveur créez un nouveau fichier nommé deletetodomutation js deletetodomutation js dans le src/mutations src/mutations répertoire contenant le code suivant 1 import { commitmutation, graphql } from "react relay"; 2 import { root id, connectionhandler } from 'relay runtime'; 3	 4 const connectiondeleteedgeupdater = (store, nodeid) => { 5 const parentproxy = store get(root id); 6 const connection = connectionhandler getconnection(parentproxy, 'todolist todos'); 7	 8 const newcount = connection getvalue('count'); 9 connection setvalue(newcount 1, 'count'); 10	 11 connectionhandler deletenode(connection, nodeid); 12 } 13	 14 const mutation = graphql` 15 mutation deletetodomutation($input deletetodoinput!) { 16 deletetodo(input $input) { 17 todo { 18 id 19 } 20 } 21 } 22 `; 23	 24 function commit({ environment, input, oncompleted, onerror }) { 25 const variables = { input }; 26	 27 commitmutation(environment, { 28 mutation, 29 variables, 30 oncompleted, 31 onerror, 32 updater (store) => { 33 connectiondeleteedgeupdater(store, input id) 34 } 35 }); 36 } 37	 38 export default { 39 commit, 40 }; tout comme dans l'étape précédente, ajoutez la fonction suivante au todolist todolist composant, qui appellera le deletetodomutation deletetodomutation et sera référencé plus tard par un bouton 1 const deletetodo = (todoid) => { 2 const input = { 3 id todoid, 4 } 5	 6 deletetodomutation commit({ 7 environment, 8 input input, 9 oncompleted () => { 10 alert alert('success!', 'todo deleted!'); 11 }, 12 onerror (errors) => { 13 alert alert('error!', errors); 14 }, 15 }); 16 } 7 utilisation de crud dans un composant react native complétons maintenant notre todolist todolist code de composant avec les éléments d'interface utilisateur stylisés, les variables d'état et les appels à vos fonctions crud 1 import react, {usestate} from 'react'; 2 import { 3 alert, 4 view, 5 safeareaview, 6 image, 7 scrollview, 8 statusbar, 9 stylesheet, 10 touchableopacity, 11 } from 'react native'; 12	 13 import { 14 list, 15 text as papertext, 16 button as paperbutton, 17 textinput as papertextinput, 18 } from 'react native paper'; 19 import {createfragmentcontainer} from 'react relay'; 20 import createtodomutation from ' /mutations/createtodomutation'; 21 import updatetodomutation from ' /mutations/updatetodomutation'; 22 import deletetodomutation from ' /mutations/deletetodomutation'; 23	 24 import environment from ' / /relay/environment'; 25	 26 const todolist = props => { 27 const \[newtodotitle, setnewtodotitle] = usestate(''); 28	 29 const {query} = props; 30 const {todos} = query; 31	 32 const createtodo = () => { 33 const input = { 34 fields { 35 title newtodotitle, 36 done false, 37 }, 38 }; 39	 40 createtodomutation commit({ 41 environment, 42 input input, 43 oncompleted () => { 44 alert alert('success!', 'todo created!'); 45 setnewtodotitle(''); 46 }, 47 onerror errors => { 48 alert alert('error!', errors); 49 }, 50 }); 51 }; 52	 53 const updatetodo = (todoid, done) => { 54 const input = { 55 id todoid, 56 fields { 57 done, 58 }, 59 }; 60	 61 updatetodomutation commit({ 62 environment, 63 input input, 64 oncompleted () => { 65 alert alert('success!', 'todo updated!'); 66 }, 67 onerror errors => { 68 alert alert('error!', errors); 69 }, 70 }); 71 }; 72	 73 const deletetodo = todoid => { 74 const input = { 75 id todoid, 76 }; 77	 78 deletetodomutation commit({ 79 environment, 80 input input, 81 oncompleted () => { 82 alert alert('success!', 'todo deleted!'); 83 }, 84 onerror errors => { 85 alert alert('error!', errors); 86 }, 87 }); 88 }; 89	 90 const rendertodos = () => { 91 if (!todos) { 92 return null; 93 } 94	 95 return todos edges map(({node todo}) => ( 96 \<list item 97 key={todo id} 98 title={todo title} 99 titlestyle={todo done ? styles todo text done styles todo text} 100 style={styles todo item} 101 right={props => ( 102 <> 103 {!todo done && ( 104 \<touchableopacity onpress={() => updatetodo(todo id, true)}> 105 \<list icon { props} icon="check" color={'#4caf50'} /> 106 \</touchableopacity> 107 )} 108	 109 \<touchableopacity onpress={() => deletetodo(todo id)}> 110 \<list icon { props} icon="close" color={'#ef5350'} /> 111 \</touchableopacity> 112 \</> 113 )} 114 /> 115 )); 116 }; 117	 118 return ( 119 <> 120 \<statusbar backgroundcolor="#208aec" /> 121 \<safeareaview style={styles container}> 122 \<view style={styles header}> 123 \<image 124 style={styles header logo} 125 source={ { 126 uri 127 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png', 128 } } 129 /> 130 \<papertext style={styles header text bold}> 131 {'react native on back4app'} 132 \</papertext> 133 \<papertext style={styles header text}>{'product creation'}\</papertext> 134 \</view> 135 \<view style={styles create todo container}> 136 {/ todo create text input /} 137 \<papertextinput 138 value={newtodotitle} 139 onchangetext={text => setnewtodotitle(text)} 140 label="new todo" 141 mode="outlined" 142 style={styles create todo input} 143 /> 144 {/ todo create button /} 145 \<paperbutton 146 onpress={() => createtodo()} 147 mode="contained" 148 icon="plus" 149 color={'#208aec'} 150 style={styles create todo button}> 151 {'add'} 152 \</paperbutton> 153 \</view> 154 \<scrollview style={styles todo list}>{rendertodos()}\</scrollview> 155 \</safeareaview> 156 \</> 157 ); 158 }; 159	 160 const todolistfragmentcontainer = createfragmentcontainer(todolist, { 161 query graphql` 162 fragment todolist query on query { 163 todos(first 1000) @connection(key "todolist todos", filters \[]) { 164 edges { 165 node { 166 id 167 title 168 done 169 } 170 } 171 } 172 } 173 `, 174 }); 175	 176 const styles = stylesheet create({ 177 container { 178 flex 1, 179 backgroundcolor '#fff', 180 }, 181 wrapper { 182 width '90%', 183 alignself 'center', 184 }, 185 header { 186 alignitems 'center', 187 paddingtop 10, 188 paddingbottom 20, 189 backgroundcolor '#208aec', 190 }, 191 header logo { 192 width 170, 193 height 40, 194 marginbottom 10, 195 resizemode 'contain', 196 }, 197 header text bold { 198 color '#fff', 199 fontsize 14, 200 fontweight 'bold', 201 }, 202 header text { 203 margintop 3, 204 color '#fff', 205 fontsize 14, 206 }, 207 flex between { 208 flexdirection 'row', 209 alignitems 'center', 210 justifycontent 'space between', 211 }, 212 create todo container { 213 flexdirection 'row', 214 paddingleft 10, 215 paddingright 10, 216 }, 217 create todo input { 218 flex 1, 219 height 38, 220 marginbottom 16, 221 backgroundcolor '#fff', 222 fontsize 14, 223 }, 224 create todo button { 225 margintop 6, 226 marginleft 15, 227 height 40, 228 }, 229 todo list { 230 paddingleft 10, 231 paddingright 10, 232 }, 233 todo item { 234 borderbottomwidth 1, 235 borderbottomcolor 'rgba(0, 0, 0, 0 12)', 236 }, 237 todo text { 238 fontsize 15, 239 }, 240 todo text done { 241 color 'rgba(0, 0, 0, 0 3)', 242 fontsize 15, 243 textdecorationline 'line through', 244 }, 245 }); 246	 247 export default todolistfragmentcontainer; avant de lancer votre projet, n'oubliez pas de lancer yarn relay yarn relay et de mettre à jour les types relay generated generated si votre composant est correctement configuré, vous devriez voir quelque chose comme ceci après avoir construit et exécuté l'application allez y et ajoutez quelques tâches en tapant leurs titres dans la zone de saisie un par un et en appuyant sur le bouton ajouter notez qu'après chaque création réussie, la createtodo createtodo fonction déclenche le rappel de mise à jour dans la mutation, actualisant automatiquement votre liste de tâches vous devriez maintenant avoir une liste de tâches conséquente comme ceci vous pouvez maintenant marquer vos tâches comme faites en cliquant sur la coche à côté, ce qui met à jour leur valeur de fait à vrai et change son statut d'icône à gauche comme indiqué dans l'étape de la fonction de mise à jour, le relay mettra automatiquement à jour le todo avec la nouvelle valeur du champ fait fait la seule opération de données restante est maintenant celle de suppression, qui peut être effectuée en appuyant sur l'icône de la poubelle à l'extrême droite de votre objet de liste de tâches après avoir supprimé un objet avec succès, vous devriez recevoir un message d'alerte comme ceci conclusion à la fin de ce guide, vous avez appris à effectuer des opérations de données de base (crud) avec grapqhql et relay modern sur react native, tout en apprenant également les api de connexion relay qui nous aident à mettre à jour notre frontend