React Native
...
Data objects
CRUD GraphQL en React Native con Relay: Guía Técnica
17 min
tutorial de crud de graphql en react native introducción gestionar datos en back4app usando graphql es una opción poderosa para cualquier tipo de aplicación, acelerando las consultas y simplificando las más complejas back4app utiliza convenciones comunes para la configuración de graphql y proporciona excelentes herramientas para ayudar a configurar tu entorno de desarrollo en esta guía, aprenderás a realizar operaciones básicas de datos a través de una aplicación de ejemplo crud, que te mostrará cómo crear, leer, actualizar y eliminar datos de tu base de datos del servidor parse en react native usando graphql y relay primero crearás tus funciones de componente para cada operación crud, utilizándolas más tarde en un diseño de pantalla completo, resultando en una aplicación de lista de tareas en cualquier momento, puedes acceder a este proyecto a través de nuestros repositorios de github para revisar los estilos y el código completo repositorio de ejemplo en javascript requisitos previos para este tutorial utilizaremos el servidor parse en la versión 4 4 si deseas usar otras versiones, puedes consultar el código de mutación correspondiente en https //www back4app com/docs/parse graphql/graphql logout mutation ejemplo para tu respectiva versión una aplicación de react native creada y conectada a back4app; concluir el tutorial de configuración del entorno de relay buena comprensión de relay store y relay connection updater; puedes leer más en documentos de relay modern usaremos javascript como la implementación predeterminada objetivo construir una aplicación crud básica en react native utilizando parse, graphql y relay 1 creando la clase todo en este primer paso, necesitamos definir la clase con la que la aplicación estará operando la todo todo clase solo necesita tener un campo de título ( string string ) que describa la tarea y un campo de hecho ( boolean boolean ) que indique si la tarea está completada puedes usar una mutación genérica para crear la clase en tu base de datos si no la tienes, siguiendo nuestra guía en el graphql cookbook https //www back4app com/docs/parse graphql/graphql mutation create object también puedes crear la clase utilizando el panel de control de back4app, a través del navegador de base de datos o desde las consolas de js o graphql después de crear esta nueva clase, recuerda descargar el schema json schema json archivo desde el panel de control y guardarlo en tu aplicación dentro del directorio data data esto es necesario para que el relay compiler genere automáticamente los tipos a partir de consultas, mutaciones, etc en este punto, tu panel de control de back4app habrá generado automáticamente mutaciones crud para el objeto de clase, para verlas puedes ir a la consola graphql, abrir la pestaña de docs y buscar todo todo 2 consultando y renderizando los objetos ahora vamos a crear un componente que será responsable de realizar la consulta de la lista en el servidor de back4app, estableciendo una conexión para los objetos y renderizando y actualizando automáticamente el contenido de la lista a medida que cambie crea un nuevo archivo llamado todolistqueryrenderer js todolistqueryrenderer js en tu src src directorio con el siguiente código 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 crear el componente de lista y el fragmento de objeto ahora vamos a crear nuestro componente de lista, que renderizará los datos recuperados del queryrenderer el componente contendrá por ahora solo una vista de desplazamiento simple que contiene una función de mapa que renderiza cada nodo adelante, crea un nuevo archivo en tu directorio src llamado todolist js todolist js y agrega el siguiente código 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 }); el renderizador de consultas en el paso 2 espera un fragmento de datos llamado todolist query todolist query , así que lo añadimos al componente de lista también al final del archivo recuerda que los fragmentos de graphql son estructuras responsables de llamar a los datos que los componentes necesitan para renderizar y especificar qué necesita ser devuelto 4 creando los objetos el primer paso para gestionar tus datos en tu base de datos graphql de back4app es tener algunos en ella necesitamos crear una función para llamar y crear un nuevo todo todo en nuestro componente de lista utilizando una mutación responsable de ello comencemos con la mutación, así que crea un nuevo archivo llamado createtodomutation js createtodomutation js en el src/mutations src/mutations directorio que contenga el siguiente código 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 nos proporciona un montón de puntos finales de api que se pueden usar para actualizar los datos después de las llamadas de mutación en esta función, usamos algunas de sus funciones para obtener el nuevo todo todo creado y actualizar la lista ya existente en el frontend con este enfoque, evitamos una nueva llamada al backend, ahorrando tiempo que se gastaría en una nueva solicitud, internet del usuario, sobrecarga de datos, y más ahora agrega la siguiente función al todolist todolist componente, que llamará a la createtodomutation createtodomutation y será referenciada más tarde por un botón 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 actualizando los objetos actualizar un objeto es similar a crearlo, con la adición de que, cuando estás actualizando un objeto usando relay modern, solo necesitas pedir los campos que deseas actualizar con el nuevo estado en la salida de la mutación crea un nuevo archivo llamado updatetodomutation js updatetodomutation js en el src/mutations src/mutations directorio que contenga el siguiente código 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 }; al igual que en el paso anterior, agrega la siguiente función al todolist todolist componente, que llamará a la updatetodomutation updatetodomutation y será referenciada más tarde por un botón 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 eliminando los objetos cuando estás eliminando un objeto, con las apis de relay store puedes actualizar la lista y eliminar el objeto antiguo del frontend llamaremos a un callback de actualización, similar a la actualización de createtodo createtodo , pero pasaremos la conexión y el id de la tarea para eliminarla de la lista de esta manera, mantenemos el frontend fielmente actualizado con nuestro servidor crea un nuevo archivo llamado deletetodomutation js deletetodomutation js en el src/mutations src/mutations directorio que contenga el siguiente código 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 }; al igual que en el paso anterior, agrega la siguiente función al todolist todolist componente, que llamará a la deletetodomutation deletetodomutation y será referenciada más tarde por un botón 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 usando crud en un componente de react native ahora completemos nuestro todolist todolist código del componente con los elementos de interfaz de usuario estilizados, variables de estado y llamadas a tus funciones 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; antes de ejecutar tu proyecto, no olvides ejecutar yarn relay yarn relay y actualizar los tipos de relay generated generated si tu componente está configurado correctamente, deberías ver algo como esto después de construir y ejecutar la aplicación adelante, agrega algunas tareas escribiendo sus títulos en el cuadro de entrada uno a la vez y presionando el botón agregar ten en cuenta que después de cada creación exitosa, el createtodo createtodo la función activa el callback del actualizador en la mutación, actualizando automáticamente tu lista de tareas ahora deberías tener una lista de tareas considerable como esta ahora puedes marcar tus tareas como hechas haciendo clic en la marca de verificación al lado de ellas, lo que hará que su valor de hecho se actualice a verdadero y cambiará su estado de ícono a la izquierda como se dijo en el paso de la función de actualización, el relay actualizará automáticamente el todo con el nuevo valor del campo hecho hecho la única operación de datos que queda ahora es la de eliminar, que se puede hacer presionando el ícono de la papelera en el extremo derecho de tu objeto de lista de tareas después de eliminar un objeto con éxito, deberías recibir un mensaje de alerta como este conclusión al final de esta guía, aprendiste cómo realizar operaciones básicas de datos (crud) con graphql y relay modern en react native, mientras también aprendías las apis de conexión de relay que nos ayudan a actualizar nuestro frontend