React Native
...
Data objects
Basic Operations
16 min
react native graphql crud tutorial introduction managing data on back4app using graphql is a powerful option for any type of application, speeding up queries and simplifying the most complex ones back4app uses common conventions for graphql configuration and provides great tools to help your environment setup for development in this guide, you will learn how to perform basic data operations through a crud example app, which will show you how to create, read, update and delete data from your parse server database in react native using graphql and relay you will first create your component functions for each crud operation, using them later in a complete screen layout, resulting in a to do list app at any time, you can access this project via our github repositories to checkout the styles and complete code javascript example repository prerequisites for this tutorial we will use the parse server in the 4 4 version if you want to use other versions you can check the corresponding mutation code at https //www back4app com/docs/parse graphql/graphql logout mutation example for your respective version a react native app created and connected to back4app; conclude the relay environment setup tutorial good understanding of relay store and relay connection updater; you can read more on relay modern docs we will be using javascript as the default implementation goal to build a basic crud application in react native using parse, graphql, and relay 1 creating the todo class in this first step, we need to define the class that the application will be operating with the todo todo class needs only to have a title( string string ) field describing the task and a done( boolean boolean ) field indicating if the task is completed you can use a generic mutation to create the class into your database if you don’t have it, following our guide in the graphql cookbook https //www back4app com/docs/parse graphql/graphql mutation create object you can also create the class using back4app’s dashboard, through the database browser itself or from the js, or graphql consoles after creating this new class, remember to download the schema json schema json file from the dashboard and save it in your application inside the data data directory this is necessary for the relay compiler to automatically generate the types from queries, mutations, etc at this point, your back4app dashboard will have automatically generate crud mutations for the class object, to see them you can go to the graphql console, open the docs tab, and search for todo todo 2 querying and rendering the objects let’s now create a component that will be responsible for making the list query in the back4app server, establishing a connection for the objects, and automatically rendering and updating the list contents as they change create a new file named todolistqueryrenderer js todolistqueryrenderer js in your src src directory with the following code 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 create the list component and fragment of object let’s now create our list component, which will render the data retrieved from the queryrenderer the component will for now contain only a simple scroll view containing a map function rendering each node go ahead and create a new file in your src directory called todolist js todolist js and add the following code 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 }); the query renderer in step 2 expects a fragment of data named todolist query todolist query , so we added it to the list component as well at the end of the file remember that graphql fragments are structures responsible for calling the data the components need to render and specifying what needs to be returned 4 creating the objects the first step to manage your data in your back4app graphql database is to have some on it we need to create a function to call to create a new todo todo in our list component using a mutation responsible for it let’s begin with the mutation, so create a new file named createtodomutation js createtodomutation js in the src/mutations src/mutations directory containing the following code 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 provides us a bunch of api endpoints to be used to update the data after mutation calls in this function, we used some of its functions to get the new todo todo created and update the already existing list on the frontend with this approach, we avoid a new call to the backend saving time that would be spent on a new request, user internet, over fetching, and more now add the following function to the todolist todolist component, which will call the createtodomutation createtodomutation and will be referenced later by a button 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 updating the objects updating an object is similar to creating it, with the addition that, when you are updating an object using relay modern, you just need to ask the fields that you want to update with the new state on the output of the mutation create a new file named updatetodomutation js updatetodomutation js in the src/mutations src/mutations directory containing the following code 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 }; just like in the previous step, add the following function to the todolist todolist component, which will call the updatetodomutation updatetodomutation and will be referenced later by a button 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 deleting the objects when you are deleting an object, with the relay store apis you can update the list and removing the old object from the frontend we will call an updater callback, similar to the update from createtodo createtodo , but we will pass the connection and the id of the to do to remove it from the list in this way, we keep the frontend faithfully updated to our server create a new file named deletetodomutation js deletetodomutation js in the src/mutations src/mutations directory containing the following code 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 }; just like in the previous step, add the following function to the todolist todolist component, which will call the deletetodomutation deletetodomutation and will be referenced later by a button 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 using crud in a react native component let´s now complete our todolist todolist component code with the styled user interface elements, state variables, and calls to your crud functions 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; before running your project, don´t forget to run yarn relay yarn relay and update the relay generated generated types if your component is properly set up, you should see something like this after building and running the app go ahead and add some to dos by typing its titles in the input box one at a time and pressing the add button note that after every successful creation, the createtodo createtodo function triggers the updater callback into the mutation, refreshing your task list automatically you should now have a sizeable to do list like this you can now mark your tasks as done by clicking in the checkmark beside it, causing their done value to be updated to true and changing its icon status on the left as said in the update function step, the relay will update automatically the todo with the new value of the field done done the only remaining data operation is now the delete one, which can be done by pressing on the trash can icon at the far right of your to do list object after successfully deleting an object, you should get an alert message like this conclusion at the end of this guide, you learned how to perform basic data operations (crud) with grapqhql and relay modern on react native, while also learning the relay connection apis that help us updating our frontend