---
title: Relationships
slug: docs/react/data-objects/relationships
description: In this guide you will learn how to create and query data object relations in Parse on React
image: https://www.back4app.com/images/logo-social.png
docTags: 
createdAt: 2024-03-18T19:00:20.273Z
---

# Relationships

## Introduction

Using Parse, you can store data objects establishing relations between them. To model this behavior, any <font color="#2166ae">`ParseObject` </font>can be used as a value in other <font color="#2166ae">`ParseObject`</font>. Internally, the Parse framework will store the referred-to object in just one place, to maintain consistency. That can give you extra power when building and running complex queries. There are three main relation types:

- <font color="#2166ae">`one-to-many`</font>, where one object can be related to many other objects;
- <font color="#2166ae">`many-to-many`</font>, which can create many complex relations between many objects.
- <font color="#2166ae">`one-to-one`</font>, establishing direct relations between two objects and only them;

There are two ways to create a <font color="#2166ae">`one-to-many`</font> relation in Parse:

- (Recomended) The first is using the <font color="#2166ae">`Parse Pointers`</font> in Child Class, which is the fastest in creation and query time. We will use this in this guide.
- The second is using <font color="#2166ae">`Arrays`</font> of <font color="#2166ae">`Parse Pointers`</font> in Parent Class which can lead to slow query times depending on their size. Because of this performance issue, we will use only pointers examples.

There are three ways to create a <font color="#2166ae">`many-to-many`</font> relation in Parse.

- (Recomended) The first is using <font color="#2166ae">`Parse Relations`</font>, which is the fastest in creation and query time. We will use this in this guide.
- The second is using <font color="#2166ae">`Arrays` </font>of <font color="#2166ae">`Parse Pointers`</font> which can lead to slow query times depending on their size.
- The third is using <font color="#2166ae">`JoinTable`</font> where the idea from classical database. When there is a many-to-nany relation, we combine every <font color="#2166ae">`objectId` </font>or <font color="#2166ae">`Pointer`</font> from both sides together to build a new separate table in which the relationship is tracked.

In this guide, you will implement a React book registration application that contains the three main kinds of data associations. You will learn how to create and query data relations using Back4App and React.

:::hint{type="success"}
At any time, you can access this project via our GitHub repositories to checkout the styles and complete code.

- [JavaScript Example Repository](https://github.com/templates-back4app/react-js-associations)
- [TypeScript Example Repository](https://github.com/templates-back4app/react-ts-associations)
:::

## Prerequisites

:::hint{type="info"}
To complete this tutorial, you will need:

- A React App created and [connected to Back4App](https://www.back4app.com/docs/react/quickstart).
-  If you want to run this guide’s example project, you should set up the [ library](https://ant.design/).
:::

## Goal

To perform and demonstrate database relations in React using Parse in a realistic scenario.

## 1 - Understanding the Book class

Since in this guide we will be using a book registration application example, you need to first understand how the object relations are laid out in this database. The main object class that you’ll be using is the <font color="#2166ae">`Book` </font>class, which will store each book entry in the registration. These are the other four object classes:

- <font color="#2166ae">`Publisher`</font>: book publisher name, one-to-many relation with <font color="#2166ae">`Book`</font>;
- <font color="#2166ae">`Genre`</font>: book genre, one-to-many relation with <font color="#2166ae">`Book`</font>. Note that for this example we will consider that a book can only have one genre;
- <font color="#2166ae">`Author`</font>: book author, many-to-many relation with <font color="#2166ae">`Book`</font>, since a book can have more than one author and an author can have more than one book as well;
- <font color="#2166ae">`ISDB`</font>: book ISDB identifying number, one-to-one relation with <font color="#2166ae">`Book`</font>, since this number is unique for each book.

Here is a visual representation of these database tables:

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/EKOHjTsqqsWc031FJC-25_image.png)

For simplicity, we will assume that each object class has only a string type <font color="#2166ae">`name`</font> attribute (<font color="#2166ae">`title` </font>for the <font color="#2166ae">`Book`</font>), apart from any additional relational attribute.

### Step 2 - Creating relations

Before going into this step we recommend you to clone and run the React app example ([JavaScript Example Repository](https://github.com/templates-back4app/react-js-associations), [TypeScript Example Repository](https://github.com/templates-back4app/react-ts-associations)). This application has two main screens: one responsible for listing the registered books and the other for creating new books. In the book registration form, there are direct links to the other related objects and a text input field assigned to the book’s ISBD value, which will be used to create the one-to-one relation.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/1o5nsf4eGyxJRRflul2ZA_image.png" size="50" width="467" height="678" position="center" showCaption="false"}

Let’s take a look at the book creation method that is called when submitting this form:

:::CodeblockTabs
JavaScript

```javascript
1   const createBook = async function () {
2     try {
3       // These values come from state variables linked to
4       // the screen form fields, retrieving the user choices
5       // as a complete Parse.Object, when applicable;
6       const bookTitleValue = bookTitle;
7       const bookISBDValue = bookISBD;
8       // For example, bookPublisher holds the value from
9       // RadioGroup field with its options being every
10      // Publisher parse object instance saved on server, which is
11      // queried on screen load via useEffect
12      const bookPublisherObject = bookPublisher;
13      const bookGenreObject = bookGenre;
14      // bookAuthors can be an array of Parse.Objects, since the book
15      // may have more than one Author
16      const bookAuthorsObjects = bookAuthors;
17
18      // Creates a new parse object instance
19      let Book = new Parse.Object('Book');
20
21      // Set data to parse object
22      // Simple title field
23      Book.set('title', bookTitleValue);
24
25      // ONE-TO-ONE (1:1)
26      // 1:1 relation, need to check for uniqueness of value before creating a new ISBD object
27      let isbdQuery = new Parse.Query('ISBD');
28      isbdQuery.equalTo('name', bookISBDValue);
29      let isbdQueryResult = await isbdQuery.first();
30      if (isbdQueryResult !== null && isbdQueryResult !== undefined) {
31        // If first returns a valid object instance, it means that there
32        // is at least one instance of ISBD with the informed value
33        alert(
34          'Error! There is already an ISBD instance with this value!',
35        );
36        return false;
37      } else {
38        // Create a new ISBD object instance to create a one-to-one relation on saving
39        let ISBD = new Parse.Object('ISBD');
40        ISBD.set('name', bookISBDValue);
41        ISBD = await ISBD.save();
42        // Set the new object to the new book object ISBD field
43        Book.set('isbd', ISBD);
44      }
45
46      // ONE-TO-MANY (1:N)
47      // One-to-many relations can be set in two ways:
48      // add direct object to field (Parse will convert to pointer on save)
49      Book.set('publisher', bookPublisherObject);
50      // or add pointer to field
51      Book.set('genre', bookGenreObject.toPointer());
52
53      // MANY-TO-MANY (N:N)
54      // Create a new relation so data can be added
55      let authorsRelation = Book.relation('authors');
56      // bookAuthorsObjects is an array of Parse.Objects,
57      // you can add to relation by adding the whole array or object by object
58      authorsRelation.add(bookAuthorsObjects);
59
60      // After setting the values, save it on the server
61      try {
62        await Book.save();
63        // Success
64        alert('Success!');
65        // Navigate back to home screen using react-router
66        history.push('/');
67        return true;
68      } catch (error) {
69        // Error can be caused by lack of Internet connection
70        alert(`Error! ${error.message}`);
71        return false;
72      }
73    } catch (error) {
74      // Error can be caused by lack of value selection
75      alert(
76        'Error! Make sure to select valid choices in Publisher, Genre and Author fields!',
77      );
78      return false;
79    }
80  };
```

TypeScript

```typescript
1   const createBook = async function (): Promise<boolean> {
2     try {
3       // These values come from state variables linked to
4       // the screen form fields, retrieving the user choices
5       // as a complete Parse.Object, when applicable;
6       const bookTitleValue: string = bookTitle;
7       const bookISBDValue: string = bookISBD;
8       // For example, bookPublisher holds the value from
9       // RadioButton.Group field with its options being every
10      // Publisher parse object instance saved on server, which is
11      // queried on screen load via useEffect
12      const bookPublisherObject: Parse.Object = bookPublisher;
13      const bookGenreObject: Parse.Object = bookGenre;
14      // bookAuthors can be an array of Parse.Objects, since the book
15      // may have more than one Author
16      const bookAuthorsObjects: [Parse.Object] = bookAuthors;
17
18      // Creates a new parse object instance
19      let Book: Parse.Object = new Parse.Object('Book');
20
21      // Set data to parse object
22      // Simple title field
23      Book.set('title', bookTitleValue);
24
25      // ONE-TO-ONE (1:1)
26      // 1:1 relation, need to check for uniqueness of value before creating a new ISBD object
27      let isbdQuery: Parse.Query = new Parse.Query('ISBD');
28      isbdQuery.equalTo('name', bookISBDValue);
29      let isbdQueryResult: Parse.Object = await isbdQuery.first();
30      if (isbdQueryResult !== null && isbdQueryResult !== undefined) {
31        // If first returns a valid object instance, it means that there
32        // is at least one instance of ISBD with the informed value
33        alert(
34          'Error! There is already an ISBD instance with this value!',
35        );
36        return false;
37      } else {
38        // Create a new ISBD object instance to create a one-to-one relation on saving
39        let ISBD: Parse.Object = new Parse.Object('ISBD');
40        ISBD.set('name', bookISBDValue);
41        ISBD = await ISBD.save();
42        // Set the new object to the new book object ISBD field
43        Book.set('isbd', ISBD);
44      }
45
46      // ONE-TO-MANY (1:N)
47      // One-to-many relations can be set in two ways:
48      // add direct object to field (Parse will convert to pointer on save)
49      Book.set('publisher', bookPublisherObject);
50      // or add pointer to field
51      Book.set('genre', bookGenreObject.toPointer());
52
53      // MANY-TO-MANY (N:N)
54      // Create a new relation so data can be added
55      let authorsRelation = Book.relation('authors');
56      // bookAuthorsObjects is an array of Parse.Objects,
57      // you can add to relation by adding the whole array or object by object
58      authorsRelation.add(bookAuthorsObjects);
59
60      // After setting the values, save it on the server
61      try {
62        await Book.save();
63        // Success
64        alert('Success!');
65        // Navigate back to home screen using react-router
66        history.push('/');
67        return true;
68      } catch (error) {
69        // Error can be caused by lack of Internet connection
70        alert(`Error! ${error.message}`);
71        return false;
72      }
73    } catch (error) {
74      // Error can be caused by lack of value selection
75      alert(
76        'Error! Make sure to select valid choices in Publisher, Genre and Author fields!',
77      );
78      return false;
79    }
80  };
```
:::

Let’s now look separately at how the three types of associations are done when creating the <font color="#2166ae">`Book` </font>object.

### One-to-many relation

Note how the <font color="#2166ae">`bookPublisherObject` </font>and <font color="#2166ae">`bookGenreObject`</font> are set to the new book <font color="#2166ae">`Parse.Object`</font> instance. See how simple it is in Parse to create a one-to-many relation: you could either assign the target object instance or a pointer to it using the <font color="#2166ae">`Parse.Object.set` </font>method, which takes two arguments: the field name and the value to be set. Parse will create a pointer data type column and a direct link on your dashboard for quick access under the hood.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/bFO60YCiQdEa9taTVctCT_image.png)

### Many-to-many relation

Look at how the <font color="#2166ae">`bookAuthorsObjects` </font>are set to the new book <font color="#2166ae">`Parse.Object`</font> instance. To create a many-to-many relation, you first need to create a new <font color="#2166ae">`Parse.Object.relation`</font> and then add the related objects to it either one by one or by passing an array of <font color="#2166ae">`Parse.Object`</font> using the <font color="#2166ae">`Parse.Object.relation.add`</font> method. Parse will create a relation type column and also a relational table on your database. Parse will also create a link for easy access to this new table in the field column in the dashboard.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/HEwkq5dNeXm4qnbQENKhm_image.png)

### One-to-one relation

See how the <font color="#2166ae">`bookISBDValue` </font>is set to the new book <font color="#2166ae">`Parse.Objec`</font>t instance. Creating and saving one-to-one and one-to-many relations in Parse are similar processes, in which you pass as an argument the <font color="#2166ae">`Parse.Object` </font>instance using the <font color="#2166ae">`Parse.Object.set`</font> method, which takes two arguments: the field name and the value to be set.

The catch here is that, before saving, you need to enforce that there are no <font color="#2166ae">`ISBD`</font> objects containing the informed ISBD ID string value in your database and that there are no <font color="#2166ae">`Book` </font>objects already related to it as well. The second part will always be true in this case, since you are creating a new <font color="#2166ae">`Book` </font>object every time. Enforcing the <font color="#2166ae">`ISBD` </font>uniqueness can be achieved by using the following highlighted query:

:::CodeblockTabs
JavaScript

```javascript
1   let isbdQuery = new Parse.Query('ISBD');
2   isbdQuery.equalTo('name', bookISBDValue);
3   let isbdQueryResult = await isbdQuery.first();
4   if (isbdQueryResult !== null && isbdQueryResult !== undefined) {
5     // If first returns a valid object instance, it means that there
6     // is at least one instance of ISBD with the informed value
7     alert(
8       'Error! There is already an ISBD instance with this value!',
9     );
10    return false;
11  }
```

TypeScript

```typescript
1   let isbdQuery: Parse.Query = new Parse.Query('ISBD');
2   isbdQuery.equalTo('name', bookISBDValue);
3   let isbdQueryResult: Parse.Object = await isbdQuery.first();
4   if (isbdQueryResult !== null && isbdQueryResult !== undefined) {
5     // If first returns a valid object instance, it means that there
6     // is at least one instance of ISBD with the informed value
7     alert(
8       'Error! There is already an ISBD instance with this value!',
9     );
10    return false;
11  }
```
:::

After successfully saving your objects, Parse will create a pointer data type column and a direct link on your dashboard as well.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/3Zhrk3HrwLQxbQQtH-OAj_image.png)

## 3 - Querying relations

Querying related objects is pretty straightforward as much of it is handled by Parse. Take a look at the query function in the book registers list screen and after we will highlight how each relation type is queried:

:::CodeblockTabs
JavaScript

```javascript
1   const queryBooks = async function () {
2     // These values come from state variables linked to
3     // the screen query RadioButton.Group fields, with its options being every
4     // parse object instance saved on server from the referred class, which is
5     // queried on screen load via useEffect; these variables retrievie the user choices
6     // as a complete Parse.Object;
7     const queryPublisherValue = queryPublisher;
8     const queryGenreValue = queryGenre;
9     const queryAuthorValue = queryAuthor;
10    const queryIsbdValue = queryIsbd;
11
12    // Reading parse objects is done by using Parse.Query
13    const parseQuery = new Parse.Query('Book');
14
15    // One-to-many queries
16    if (queryPublisherValue !== '') {
17      parseQuery.equalTo('publisher', queryPublisherValue);
18    }
19    if (queryGenreValue !== '') {
20      parseQuery.equalTo('genre', queryGenreValue);
21    }
22
23    // One-to-one query
24    if (queryIsbdValue !== '') {
25      parseQuery.equalTo('isbd', queryIsbdValue);
26    }
27
28    // Many-to-many query
29    // In this case, we need to retrieve books related to the chosen author
30    if (queryAuthorValue !== '') {
31      parseQuery.equalTo('authors', queryAuthorValue);
32    }
33
34    try {
35      let books = await parseQuery.find();
36      // Many-to-many objects retrieval
37      // In this example we need to get every related author Parse.Object
38      // and add it to our query result objects
39      for (let book of books) {
40        // This query is done by creating a relation and querying it
41        let bookAuthorsRelation = book.relation('authors');
42        book.authorsObjects = await bookAuthorsRelation.query().find();
43      }
44      setQueriedBooks(books);
45      return true;
46    } catch (error) {
47      // Error can be caused by lack of Internet connection
48      alert(`Error! ${error.message}`);
49      return false;
50    }
51  };
```

TypeScript

```typescript
1   const queryBooks = async function (): Promise<boolean> {
2     // These values come from state variables linked to
3     // the screen query RadioButton.Group fields, with its options being every
4     // parse object instance saved on server from the referred class, which is
5     // queried on screen load via useEffect; these variables retrievie the user choices
6     // as a complete Parse.Object;
7     const queryPublisherValue: Parse.Object = queryPublisher;
8     const queryGenreValue: Parse.Object = queryGenre;
9     const queryAuthorValue: Parse.Object = queryAuthor;
10    const queryIsbdValue: Parse.Object = queryIsbd;
11
12    // Reading parse objects is done by using Parse.Query
13    const parseQuery: Parse.Query = new Parse.Query('Book');
14
15    // One-to-many queries
16    if (queryPublisherValue !== '') {
17      parseQuery.equalTo('publisher', queryPublisherValue);
18    }
19    if (queryGenreValue !== '') {
20      parseQuery.equalTo('genre', queryGenreValue);
21    }
22
23    // One-to-one query
24    if (queryIsbdValue !== '') {
25      parseQuery.equalTo('isbd', queryIsbdValue);
26    }
27
28    // Many-to-many query
29    // In this case, we need to retrieve books related to the chosen author
30    if (queryAuthorValue !== '') {
31      parseQuery.equalTo('authors', queryAuthorValue);
32    }
33
34    try {
35      let books: [Parse.Object] = await parseQuery.find();
36      // Many-to-many objects retrieval
37      // In this example we need to get every related author Parse.Object
38      // and add it to our query result objects
39      for (let book of books) {
40        // This query is done by creating a relation and querying it
41        let bookAuthorsRelation = book.relation('authors');
42        book.authorsObjects = await bookAuthorsRelation.query().find();
43      }
44      setQueriedBooks(books);
45      return true;
46    } catch (error) {
47      // Error can be caused by lack of Internet connection
48      alert(`Error! ${error.message}`);
49      return false;
50    }
51  };
```
:::

### One-to-many query

To query any books related to a specific publisher or genre, you need to perform a <font color="#2166ae">`Parse.Query.equalT`</font>o method passing the <font color="#2166ae">`Parse.Object`</font> instance as the parameter. After querying, Parse will store inside the resulting objects the complete instances of any one-to-many relational fields. To retrieve and show data from these object instances, you can chain the <font color="#2166ae">`Parse.Object.get`</font> method like this: <font color="#2166ae">`BookParseObject.get(('publisher').get('name').`</font>

### Many-to-many query

To query any books related to a specific author, the query will also use only a <font color="#2166ae">`Parse.Query.equalTo`</font> method. However, after querying, Parse will not store <font color="#2166ae">`Parse.Object`</font> instances from many-to-many relational fields, only a reference to the related class name, such as <font color="#2166ae">`{"__type": "Relation", "className": "Author"}`</font>. To retrieve and show data from these object instances, you need to create a relation and query it again, storing the results in an object array of your own.

### One-to-one query

Just as before, to query any books related to a specific ISBD, you need to perform a <font color="#2166ae">`Parse.Query.equalTo`</font> method passing the <font color="#2166ae">`Parse.Object`</font> instance as the parameter. After querying, Parse will store inside the resulting objects the complete instances of any one-to-one relational fields, the same way that it is done with one-to-many relational fields.

## Conclusion

At the end of this guide, you learned how to create and query relations in Parse on React. In the next guide, we will show you how to register users.
