Storing data on Parse is built around the Parse.Object class. Each Parse.Object contains key-value pairs of JSON-compatible data. This data is schemaless, which means that you don’t need to specify ahead of time what keys exist on each Parse.Object. You can simply set whatever key-value pairs you want, and our backend will store it.
You can also specify the datatypes according to your application needs and persist types such as number, boolean, string, DateTime, list, GeoPointers, and Object, encoding them to JSON before saving. Parse also supports store and query relational data by using the types Pointers and Relations.
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. 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.
If you want to test/use the screen layout provided by this guide, you should set up the Ant Designlibrary.
Goal
To build a basic CRUD application in React using Parse.
1 - Creating data objects
The first step to manage your data in your Parse database is to have some on it. Let’s now make a createTodo function that will create a new instance of Parse.Object with the “Todo” subclass. The to-do will have a title (string) describing the task and a done(boolean) field indicating whether the task is completed.
JavaScript
TypeScript
1constcreateTodo=asyncfunction(){2// This value comes from a state variable3const newTodoTitleValue = newTodoTitle;4// Creates a new Todo parse object instance5let Todo =newParse.Object('Todo');6 Todo.set('title', newTodoTitleValue);7 Todo.set('done',false);8// After setting the to-do values, save it on the server9try{10await Todo.save();11// Success12alert('Success! To-do created!');13// Refresh to-dos list to show the new one (you will create this function later)14readTodos();15returntrue;16}catch(error){17// Error can be caused by lack of Internet connection18alert(`Error! ${error.message}`);19returnfalse;20};21};
Notice that if your database does not have a Todo table (or subclass) in it yet, Parse will create it automatically and also add any columns set inside the Parse.Object instance using the Parse.Object.set() method, which takes two arguments: the field name and the value to be set.
2 - Reading data objects
After creating some data in your database, your application can now be able to read it from the server and show it to your user. Go ahead and create a readTodos function, which will perform a Parse.Query, storing the result inside a state variable.
JavaScript
TypeScript
1constreadTodos=asyncfunction(){2// Reading parse objects is done by using Parse.Query3const parseQuery =newParse.Query('Todo');4try{5let todos =await parseQuery.find();6// Be aware that empty or invalid queries return as an empty array7// Set results to state variable8setReadResults(todos);9returntrue;10}catch(error){11// Error can be caused by lack of Internet connection12alert(`Error! ${error.message}`);13returnfalse;14};15};
Many constraints and orderings can be applied to your queries using the Parse.Query class, but for now, we will stick to this simple query, which will retrieve every saved Todo object.
3 - Updating data objects
Updating a Parse.Object instance is very similar to creating a new one, except that in this case, you need to assign the previously created objectId to it and then save, after setting your new values.
JavaScript
TypeScript
1constupdateTodo=asyncfunction(todoId, done){2// Create a new Todo parse object instance and set todo id3let Todo =newParse.Object('Todo');4 Todo.set('objectId', todoId);5// Set new done value and save Parse Object changes6 Todo.set('done', done);7try{8await Todo.save();9// Success10alert('Success! To-do updated!');11// Refresh to-dos list12readTodos();13returntrue;14}catch(error){15// Error can be caused by lack of Internet connection16alert(`Error! ${error.message}`);17returnfalse;18};19};
Since this example app represents a to-do list, your update function takes an additional argument, the done value, which will represent if the specific task is completed or not.
4 - Deleting data objects
To delete a data object, you need to call the .destroy() method in the Parse.Object instance representing it. Please be careful because this operation is not reversible.
JavaScript
TypeScript
1constdeleteTodo=asyncfunction(todoId:string):Promise<boolean>{2// Create a new Todo parse object instance and set todo id3let Todo: Parse.Object =newParse.Object('Todo');4 Todo.set('objectId', todoId);5// .destroy should be called to delete a parse object6try{7await Todo.destroy();8alert('Success! To-do deleted!');9// Refresh to-dos list to remove this one10readTodos();11returntrue;12}catch(error:any){13// Error can be caused by lack of Internet connection14alert(`Error! ${error.message}`);15returnfalse;16};17};
Let’s now use these four functions in a complete component, so you can test it and make sure that every CRUD operation is working properly.
5 - Using CRUD in a React component
Here is the complete component code, including styled user interface elements (using Ant Design), state variables, and calls to your CRUD functions. You should create a separate component in a file called TodoList.js/TodoList.tsx in your src directory containing the following code or add it directly to your main application file (App.js/App.tsx).
TodoList.js
TodoList.tsx
1import React,{ useState,FC, ReactElement }from'react';2import'./App.css';3import{ Button, Input, List }from'antd';4import{5 CheckOutlined,6 CloseOutlined,7 PlusOutlined,8 RedoOutlined,9}from'@ant-design/icons';10const Parse =require('parse/dist/parse.min.js');1112exportconst TodoList:FC<{}>=(): ReactElement =>{13// State variables14const initialReadResults: Parse.Object[]=[];15const[readResults, setReadResults]=useState(initialReadResults);16const[newTodoTitle, setNewTodoTitle]=useState('');1718// Functions used by the screen components19constcreateTodo=asyncfunction():Promise<boolean>{20// This value comes from a state variable21const newTodoTitleValue:string= newTodoTitle;22// Creates a new Todo parse object instance23let Todo: Parse.Object =newParse.Object('Todo');24 Todo.set('title', newTodoTitleValue);25 Todo.set('done',false);26// After setting the to-do values, save it on the server27try{28await Todo.save();29// Success30alert('Success! To-do created!');31// Refresh to-dos list to show the new one (you will create this function later)32readTodos();33returntrue;34}catch(error:any){35// Error can be caused by lack of Internet connection36alert('Error!'+ error.message);37returnfalse;38}39};4041constreadTodos=asyncfunction():Promise<boolean>{42// Reading parse objects is done by using Parse.Query43const parseQuery: Parse.Query =newParse.Query('Todo');44try{45let todos: Parse.Object[]=await parseQuery.find();46// Be aware that empty or invalid queries return as an empty array47// Set results to state variable48setReadResults(todos);49returntrue;50}catch(error:any){51// Error can be caused by lack of Internet connection52alert('Error!'+ error.message);53returnfalse;54}55};5657constupdateTodo=asyncfunction(todoId:string, done:boolean):Promise<boolean>{58// Create a new to-do parse object instance and set todo id59let Todo: Parse.Object =newParse.Object('Todo');60 Todo.set('objectId', todoId);61// Set new done value and save Parse Object changes62 Todo.set('done', done);63try{64await Todo.save();65// Success66alert('Success! To-do updated!');67// Refresh todos list68readTodos();69returntrue;70}catch(error:any){71// Error can be caused by lack of Internet connection72alert('Error!'+ error.message);73returnfalse;74}75};7677constdeleteTodo=asyncfunction(todoId:string):Promise<boolean>{78// Create a new Todo parse object instance and set todo id79let Todo: Parse.Object =newParse.Object('Todo');80 Todo.set('objectId', todoId);81// .destroy should be called to delete a parse object82try{83await Todo.destroy();84alert('Success! To-do deleted!');85// Refresh to-dos list to remove this one86readTodos();87returntrue;88}catch(error:any){89// Error can be caused by lack of Internet connection90alert('Error!'+ error.message);91returnfalse;92}93};9495return(96<div>97<div className="header">98<img
99 className="header_logo"100 alt="Back4App Logo"101 src={102'https://blog.back4app.com/wp-content/uploads/2019/05/back4app-white-logo-500px.png'103}104/>105<p className="header_text_bold">{'React on Back4App'}</p>106<p className="header_text">{'To-do List'}</p>107</div>108<div className="container">109<div className="flex_between">110<h2 className="list_heading">Todo List</h2>111{/* To-do read (refresh) button */}112<Button
113 type="primary"114 shape="circle"115 color={'#208AEC'}116 onClick={readTodos}117 icon={<RedoOutlined />}118></Button>119</div>120<div className="new_todo_wrapper flex_between">121{/* Todo create text input */}122<Input
123 value={newTodoTitle}124 onChange={(event:{target:{value:string}})=>setNewTodoTitle(event.target.value)}125 placeholder="New Todo"126 size="large"127/>128{/* Todo create button */}129<Button
130 type="primary"131 className="create_todo_button"132 color={'#208AEC'}133 size={'large'}134 onClick={createTodo}135 icon={<PlusOutlined />}136>137 Add
138</Button>139</div>140<div>141{/* Todo read results list */}142{readResults !==null&&143 readResults !==undefined&&144 readResults.length >0&&(145<List
146 dataSource={readResults}147 renderItem={(item: Parse.Object)=>(148<List.Item className="todo_item">149<p
150 className={151 item.get('done')===true152?'todo_text_done'153:'todo_text'154}155>156{item.get('title')}157</p>158<div className="flex_row">159{/* Todo update button */}160{item.get('done')!==true&&(161<Button
162 type="primary"163 shape="circle"164 className="todo_button"165 onClick={()=>updateTodo(item.id,true)}166 icon={167<CheckOutlined className="todo_button_icon_done"/>168}169></Button>170)}171{/* Todo delete button */}172<Button
173 type="primary"174 shape="circle"175 className="todo_button"176 onClick={()=>deleteTodo(item.id)}177 icon={178<CloseOutlined className="todo_button_icon_remove"/>179}180></Button>181</div>182</List.Item>183)}184/>185)}186</div>187</div>188</div>189);190};
Also, add these CSS styles at the end of your App.css file:
If your component is properly set up, you should see something like this after running the app:
Go ahead and add some to-dos by typing its titles in the input box one at a time and pressing on the Add button. Note that after every successful creation, the createTodo function triggers the readTodos one, 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.
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) in Parse on React. In the next guide, we will show you which data types are supported in Parse and how to use them.