React Native

Parse Data Types in a React Native component

Introduction

In the heart of Parse Core feature is the data objects management. Parse allows you to store and query its data straightforwardly using its SDKs or APIs(REST or GraphQL). All the data object features are built using the Parse.Object class, which fields may contain key-value pairs of several JSON-compatible data types. The primary data types that can be assigned to the object fields are the following:

  • Number: integer (42) or floating-point (42.5) numbers, as long as ‘.’ is the decimal separator;
  • boolean: true or false values;
  • string: a string that can be as long as 2147483647 characters. Be aware that values this huge will slow down data operations;
  • DateTime: DateTime objects stored in UTC format as default. If you need to use another timezone, conversion should be done manually;
  • array: an array containing data in any Parse compatible data.
  • object: a JSON object also containing any Parse data. When available in SDK, an include() call will bring details from the Object property.

When you choose to use the Array type, we recommend keeping array objects small as this can affect your data operations’ overall performance. Our recommendation is to use the Array type if it does not exceed 20 elements and does not grow over time. Instead of the Array type, you can use the Pointer and Relations types as an alternative.

In this guide, you will learn how to store data in each of the basic data types listed above. You will build a React Native product registration component, which will show you how to format, convert and save data to your Parse Server in React Native.

Parse also offers the datatypes GeoPoint to use the power of geolocation resources, and the Parse-specific relational data using the types Pointer or Relation. You will see both covered in the next following guides.

Prerequisites

To complete this tutorial, you will need:

Goal

To understand the Parse-compatible basic data types, and to store each data type on Parse froma React Native component.

Step 1 - The Product Creation Component

Let’s first create the component structure. Let’s make it simple and create a form screen with one text inputs to each data type, one switch toggle, and a submit button to save the object. These inputs will collect your Product field values: name(string), quantity(number), price(number), available(boolean), expiration date(DateTime), and categories(array). Also, you will save an additional object type field in your saving method as well, but this one won’t need an input field.

Create a separate component in a file called ProductCreation.js/ProductCreation.tsx including the following code, or add it to your main application file (App.js/App.tsx or index.js). You can use this layout with complete stylings using react-native-paper or set up your custom form.

ProductCreation.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import React, {useState} from 'react';
import {
  Alert,
  Image,
  SafeAreaView,
  StatusBar,
  StyleSheet,
  View,
} from 'react-native';
import Parse from 'parse/react-native';
import {
  Button as PaperButton,
  Switch as PaperSwitch,
  Text as PaperText,
  TextInput as PaperTextInput,
} from 'react-native-paper';

export const ProductCreation = () => {
  // State variables
  const [productName, setProductName] = useState('');
  const [productQuantity, setProductQuantity] = useState('');
  const [productPrice, setProductPrice] = useState('');
  const [productAvailable, setProductAvailable] = useState(false);
  const [productExpirationDate, setProductExpirationDate] = useState('');
  const [productCategories, setProductCategories] = useState('');

  const toggleProductAvailable = () => setProductAvailable(!productAvailable);

  return (
    <>
      <StatusBar backgroundColor="#208AEC" />
      <SafeAreaView style={Styles.container}>
        <View style={Styles.header}>
          <Image
            style={Styles.header_logo}
            source={ { uri: 'https://blog.back4app.com/wp-content/uploads/2019/05/back4app-white-logo-500px.png', } }
          />
          <PaperText style={Styles.header_text_bold}>
            {'React Native on Back4App'}
          </PaperText>
          <PaperText style={Styles.header_text}>{'Product Creation'}</PaperText>
        </View>
        <View style={Styles.wrapper}>
          {/* Boolean type input  */}
          <View style={Styles.switch_container}>
            <PaperText>{'Available?'}</PaperText>
            <PaperSwitch
              value={productAvailable}
              onValueChange={toggleProductAvailable}
            />
          </View>
          {/* String type input */}
          <PaperTextInput
            value={productName}
            onChangeText={(text) => setProductName(text)}
            label="Name"
            mode="outlined"
            style={Styles.form_input}
          />
          {/* Number type input (integer) */}
          <PaperTextInput
            value={productQuantity}
            onChangeText={(text) => setProductQuantity(text)}
            label="Quantity"
            mode="outlined"
            keyboardType={'number-pad'}
            style={Styles.form_input}
          />
          {/* Number type input (float) */}
          <PaperTextInput
            value={productPrice}
            onChangeText={(text) => setProductPrice(text)}
            label="Price"
            mode="outlined"
            keyboardType={'numeric'}
            style={Styles.form_input}
          />
          {/* Date type input  */}
          <PaperTextInput
            value={productExpirationDate}
            onChangeText={(text) => setProductExpirationDate(text)}
            label="Expiration Date (mm/dd/yyyy)"
            mode="outlined"
            keyboardType={'numbers-and-punctuation'}
            style={Styles.form_input}
          />
          {/* Array type input  */}
          <PaperTextInput
            value={productCategories}
            onChangeText={(text) => setProductCategories(text)}
            label="Categories (separated by commas)"
            mode="outlined"
            style={Styles.form_input}
          />
          {/* Product create button */}
          <PaperButton
            onPress={() => createProduct()}
            mode="contained"
            icon="plus"
            style={Styles.submit_button}>
            {'Create Product'}
          </PaperButton>
        </View>
      </SafeAreaView>
    </>
  );
};

// These define the screen component styles
const Styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FFF',
  },
  wrapper: {
    width: '90%',
    alignSelf: 'center',
  },
  header: {
    alignItems: 'center',
    paddingTop: 10,
    paddingBottom: 20,
    backgroundColor: '#208AEC',
  },
  header_logo: {
    width: 170,
    height: 40,
    marginBottom: 10,
    resizeMode: 'contain',
  },
  header_text_bold: {
    color: '#fff',
    fontSize: 14,
    fontWeight: 'bold',
  },
  header_text: {
    marginTop: 3,
    color: '#fff',
    fontSize: 14,
  },
  form_input: {
    height: 44,
    marginBottom: 16,
    backgroundColor: '#FFF',
    fontSize: 14,
  },
  switch_container: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingVertical: 12,
    marginBottom: 16,
    borderBottomWidth: 1,
    borderBottomColor: 'rgba(0, 0, 0, 0.3)',
  },
  submit_button: {
    width: '100%',
    maxHeight: 50,
    alignSelf: 'center',
    backgroundColor: '#208AEC',
  },
});

ProductCreation.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import React, {FC, ReactElement, useState} from 'react';
import {
  Alert,
  Image,
  SafeAreaView,
  StatusBar,
  StyleSheet,
  View,
} from 'react-native';
import Parse from 'parse/react-native';
import {
  Button as PaperButton,
  Switch as PaperSwitch,
  Text as PaperText,
  TextInput as PaperTextInput,
} from 'react-native-paper';

export const ProductCreation: FC<{}> = ({}): ReactElement => {
  // State variables
  const [productName, setProductName] = useState('');
  const [productQuantity, setProductQuantity] = useState('');
  const [productPrice, setProductPrice] = useState('');
  const [productAvailable, setProductAvailable] = useState(false);
  const [productExpirationDate, setProductExpirationDate] = useState('');
  const [productCategories, setProductCategories] = useState('');

  const toggleProductAvailable = () => setProductAvailable(!productAvailable);

  return (
    <>
      <StatusBar backgroundColor="#208AEC" />
      <SafeAreaView style={Styles.container}>
        <View style={Styles.header}>
          <Image
            style={Styles.header_logo}
            source={ { uri: 'https://blog.back4app.com/wp-content/uploads/2019/05/back4app-white-logo-500px.png', } }
          />
          <PaperText style={Styles.header_text_bold}>
            {'React Native on Back4App'}
          </PaperText>
          <PaperText style={Styles.header_text}>{'Product Creation'}</PaperText>
        </View>
        <View style={Styles.wrapper}>
          {/* Boolean type input  */}
          <View style={Styles.switch_container}>
            <PaperText>{'Available?'}</PaperText>
            <PaperSwitch
              value={productAvailable}
              onValueChange={toggleProductAvailable}
            />
          </View>
          {/* String type input */}
          <PaperTextInput
            value={productName}
            onChangeText={(text) => setProductName(text)}
            label="Name"
            mode="outlined"
            style={Styles.form_input}
          />
          {/* Number type input (integer) */}
          <PaperTextInput
            value={productQuantity}
            onChangeText={(text) => setProductQuantity(text)}
            label="Quantity"
            mode="outlined"
            keyboardType={'number-pad'}
            style={Styles.form_input}
          />
          {/* Number type input (float) */}
          <PaperTextInput
            value={productPrice}
            onChangeText={(text) => setProductPrice(text)}
            label="Price"
            mode="outlined"
            keyboardType={'numeric'}
            style={Styles.form_input}
          />
          {/* Date type input  */}
          <PaperTextInput
            value={productExpirationDate}
            onChangeText={(text) => setProductExpirationDate(text)}
            label="Expiration Date (mm/dd/yyyy)"
            mode="outlined"
            keyboardType={'numbers-and-punctuation'}
            style={Styles.form_input}
          />
          {/* Array type input  */}
          <PaperTextInput
            value={productCategories}
            onChangeText={(text) => setProductCategories(text)}
            label="Categories (separated by commas)"
            mode="outlined"
            style={Styles.form_input}
          />
          {/* Product create button */}
          <PaperButton
            onPress={() => createProduct()}
            mode="contained"
            icon="plus"
            style={Styles.submit_button}>
            {'Create Product'}
          </PaperButton>
        </View>
      </SafeAreaView>
    </>
  );
};

// These define the screen component styles
const Styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FFF',
  },
  wrapper: {
    width: '90%',
    alignSelf: 'center',
  },
  header: {
    alignItems: 'center',
    paddingTop: 10,
    paddingBottom: 20,
    backgroundColor: '#208AEC',
  },
  header_logo: {
    width: 170,
    height: 40,
    marginBottom: 10,
    resizeMode: 'contain',
  },
  header_text_bold: {
    color: '#fff',
    fontSize: 14,
    fontWeight: 'bold',
  },
  header_text: {
    marginTop: 3,
    color: '#fff',
    fontSize: 14,
  },
  form_input: {
    height: 44,
    marginBottom: 16,
    backgroundColor: '#FFF',
    fontSize: 14,
  },
  switch_container: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingVertical: 12,
    marginBottom: 16,
    borderBottomWidth: 1,
    borderBottomColor: 'rgba(0, 0, 0, 0.3)',
  },
  submit_button: {
    width: '100%',
    maxHeight: 50,
    alignSelf: 'center',
    backgroundColor: '#208AEC',
  },
});

After setting up this screen, your application should look like this:

React Native Back4App

Note that each Product attribute has its text input field, except for the boolean switch input, meaning that the data in them needs conversion to the corresponding data type before saving.

Step 2 - Converting input data

Before saving your data to the Parse.object, you need to correctly format the number, DateTime, and array inputs. Let’s now create a saving function, which will retrieve data from your state variables and apply the suitable data conversion:

ProductCreation.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const createProduct = async function () {
  try {
    // These values come from state variables
    // Convert data values to corresponding data types
    const productNameValue = productName;
    const productQuantityValue = Number(productQuantity);
    const productPriceValue = Number(productPrice);
    const productAvailableValue = productAvailable;
    const productExpirationDateValue = new Date(productExpirationDate);
    const productCategoriesValue = productCategories.split(',');
  } catch (error) {
    // Error can be caused by wrong type of values in fields
    Alert.alert('Error!', error.message);
    return false;
  }
};

ProductCreation.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const createProduct = async function (): Promise<[boolean]> {
  try {
    // These values come from state variables
    // Convert data values to corresponding data types
    const productNameValue: string = productName;
    const productQuantityValue: number = Number(productQuantity);
    const productPriceValue: number = Number(productPrice);
    const productAvailableValue: boolean = productAvailable;
    const productExpirationDateValue: Date = new Date(productExpirationDate);
    const productCategoriesValue: string[] = productCategories.split(',');
  } catch (error) {
    // Error can be caused by wrong type of values in fields
    Alert.alert('Error!', error.message);
    return false;
  }
};

The number data conversion is done casting the value as a Number JavaScript object. DateTime is converted using the Date JavaScript object constructor; the array one is created by using the String.split method in JavaScript, creating an array containing each entry of the categories field separated by commas.

Note that your data is now contained inside a single object, which can be set in a new Parse.object instance to be saved to the server using the Parse.Object.set() method, which takes two arguments: the field name and the value to be set. Let’s also set a new field called completeData, which will be your object type field, assigning the same data object to it.

Go ahead and complete the createProduct function with the following:

ProductCreation.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const createProduct = async function () {
  try {
    // These values come from state variables
    // Convert data values to corresponding data types
    const productNameValue = productName;
    const productQuantityValue = Number(productQuantity);
    const productPriceValue = Number(productPrice);
    const productAvailableValue = productAvailable;
    const productExpirationDateValue = new Date(productExpirationDate);
    const productCategoriesValue = productCategories.split(',');
  } catch (error) {
    // Error can be caused by wrong type of values in fields
    Alert.alert('Error!', error.message);
    return false;
  }

  // Creates a new Product parse object instance
  let Product = new Parse.Object('Product');
  
  // Set data to parse object
  Product.set('name', productNameValue);
  Product.set('quantity', productQuantityValue);
  Product.set('price', productPriceValue);
  Product.set('available', productAvailableValue);
  Product.set('expirationDate', productExpirationDateValue);
  Product.set('categories', productCategoriesValue);
  Product.set('completeData', {
    name: productNameValue,
    quantity: productQuantityValue,
    price: productPriceValue,
    available: productAvailableValue,
    expirationDate: productExpirationDateValue,
    categories: productCategoriesValue,
  });

  // After setting the values, save it on the server
  try {
    let savedProduct = await Product.save();
    // Success
    Alert.alert('Success!', JSON.stringify(savedProduct));
    return true;
  } catch (error) {
    // Error can be caused by lack of Internet connection
    Alert.alert('Error!', error.message);
    return false;
  };
};

ProductCreation.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const createProduct = async function (): Promise<[boolean]> {
  try {
    // These values come from state variables
    // Convert data values to corresponding data types
    const productNameValue: string = productName;
    const productQuantityValue: number = Number(productQuantity);
    const productPriceValue: number = Number(productPrice);
    const productAvailableValue: boolean = productAvailable;
    const productExpirationDateValue: Date = new Date(productExpirationDate);
    const productCategoriesValue: string[] = productCategories.split(',');
  } catch (error) {
    // Error can be caused by wrong type of values in fields
    Alert.alert('Error!', error.message);
    return false;
  }

  // Creates a new Product parse object instance
  let Product: Parse.Object = new Parse.Object('Product');
  
  // Set data to parse object
  Product.set('name', productNameValue);
  Product.set('quantity', productQuantityValue);
  Product.set('price', productPriceValue);
  Product.set('available', productAvailableValue);
  Product.set('expirationDate', productExpirationDateValue);
  Product.set('categories', productCategoriesValue);
  Product.set('completeData', {
    name: productNameValue,
    quantity: productQuantityValue,
    price: productPriceValue,
    available: productAvailableValue,
    expirationDate: productExpirationDateValue,
    categories: productCategoriesValue,
  });

  // After setting the values, save it on the server
  try {
    let savedProduct: Parse.Object = await Product.save();
    // Success
    Alert.alert('Success!', JSON.stringify(savedProduct));
    return true;
  } catch (error) {
    // Error can be caused by lack of Internet connection
    Alert.alert('Error!', error.message);
    return false;
  };
};

You can now test the component, insert the createProduct function in it, and call it inside your form submit button onPress property. After creating a product, you should see an alert containing its data like this:

React Native Back4App

To certify that your data was saved on the server using the correct data types, you can look at your Parse dashboard. Click on the Product data table and note that every column has its data type written at the header. Your class should look like this:

React Native Back4App

Conclusion

At the end of this guide, you learned how to save each of the basic data types available on Parse using a React Native component. In the next guide, you will learn about the relational data on Parse.