diff --git a/examples/react-native/.eslintrc.js b/examples/react-native/.eslintrc.js
index 2d4f5aa685..af888a5853 100644
--- a/examples/react-native/.eslintrc.js
+++ b/examples/react-native/.eslintrc.js
@@ -12,6 +12,7 @@ module.exports = {
'no-undef': 'off',
'no-new': 'off',
'jsx-quotes': 0, // do not remove this line, this removes the requirement for double quotes in jsx/tsx. The single quotes in jsx help bluehawk replace testIDs in the generated snippets for the docs
+ 'react-hooks/exhaustive-deps': 0,
'react/jsx-max-props-per-line': [0, {'maximum': 4, 'when': 'multiline'}],
},
};
diff --git a/examples/react-native/__tests__/js/models/Cat.js b/examples/react-native/__tests__/js/models/Cat.js
new file mode 100644
index 0000000000..9c7d4ac922
--- /dev/null
+++ b/examples/react-native/__tests__/js/models/Cat.js
@@ -0,0 +1,13 @@
+import Realm from 'realm';
+// :snippet-start: js-cat-schema
+class Cat extends Realm.Object {
+ static schema = {
+ name: 'Cat',
+ properties: {
+ name: 'string',
+ birthDate: 'mixed',
+ },
+ };
+}
+// :snippet-end:
+export default Cat;
diff --git a/examples/react-native/__tests__/js/realm-database/schemas/mixed-tests.jsx b/examples/react-native/__tests__/js/realm-database/schemas/mixed-tests.jsx
new file mode 100644
index 0000000000..504b6d243d
--- /dev/null
+++ b/examples/react-native/__tests__/js/realm-database/schemas/mixed-tests.jsx
@@ -0,0 +1,149 @@
+import React, {useEffect} from 'react';
+import {Text, View} from 'react-native';
+import {render, waitFor} from '@testing-library/react-native';
+import Realm from 'realm';
+import {createRealmContext} from '@realm/react';
+import Cat from '../../models/Cat';
+
+jest.setTimeout(30000);
+
+const realmConfig = {
+ schema: [Cat],
+ deleteRealmIfMigrationNeeded: true,
+};
+
+const {RealmProvider, useRealm, useQuery} = createRealmContext(realmConfig);
+
+let assertionRealm;
+
+describe('Mixed Tests', () => {
+ beforeEach(async () => {
+ // we will use this Realm for assertions to access Realm Objects outside of a Functional Component (like required by @realm/react)
+ assertionRealm = await Realm.open(realmConfig);
+
+ // delete every object in the realmConfig in the Realm to make test idempotent
+ assertionRealm.write(() => {
+ assertionRealm.delete(assertionRealm.objects(Cat));
+
+ new Cat(assertionRealm, {
+ name: 'Clover',
+ birthDate: new Date('January 21, 2016'),
+ });
+ });
+ });
+ afterAll(() => {
+ if (!assertionRealm.isClosed) {
+ assertionRealm.close();
+ }
+ });
+ it('should create an object with a mixed value', async () => {
+ // :snippet-start: create-mixed-object
+ // :replace-start: {
+ // "terms": {
+ // " testID='catItem'": ""
+ // }
+ // }
+ const CreateCatsInput = () => {
+ const realm = useRealm();
+
+ useEffect(() => {
+ // Add data to the Realm when the component mounts
+ realm.write(() => {
+ // create a Cat with a birthDate value of type string
+ new Cat(realm, {
+ name: 'Euler',
+ birthDate: 'December 25th, 2017',
+ });
+ // create a Cat with a birthDate value of type date
+ new Cat(realm, {
+ name: 'Blaise',
+ birthDate: new Date('August 17, 2020'),
+ });
+
+ // create a Cat with a birthDate value of type int
+ new Cat(realm, {name: 'Euclid', birthDate: 10152021});
+
+ // create a Cat with a birthDate value of type null
+ new Cat(realm, {name: 'Pythagoras', birthDate: null});
+ });
+ }, []);
+
+ // retrieve all cats
+ const cats = useQuery(Cat);
+
+ return (
+ <>
+ {cats.map(cat => (
+
+ {cat.name}
+ {String(cat.birthDate)}
+
+ ))}
+ >
+ );
+ };
+ // :replace-end:
+ // :snippet-end:
+
+ const App = () => (
+
+
+
+ );
+
+ const {getAllByTestId} = render();
+
+ const catItems = await waitFor(() => getAllByTestId('catItem'), {
+ timeout: 5000,
+ });
+
+ // Test that 5 Cat Items have been added to the UI,
+ // and 5 matching Cat objects have been created in the assertionRealm
+ // (since there was already 1 cat object 'clover' created in the beforeEach)
+ // + the 4 new Cats
+ setTimeout(() => {
+ expect(catItems.length).toBe(5);
+ const cats = assertionRealm.objects(Cat);
+ expect(cats.length).toBe(5);
+ }, 5500);
+ });
+ it('should query for objects with a mixed value', async () => {
+ // :snippet-start: query-mixed-object
+ // :replace-start: {
+ // "terms": {
+ // " testID='catBirthDate'": ""
+ // }
+ // }
+ const CatInfoCard = ({catName}) => {
+ // To query for the cat's birthDate, filter for their name to retrieve the realm object.
+ // Use dot notation to access the birthDate property.
+ const cat = useQuery(Cat).filtered(`name = '${catName}'`)[0];
+ const catBirthDate = cat.birthDate;
+
+ if (cat) {
+ return (
+ <>
+ {catName}
+ {String(catBirthDate)}
+ >
+ );
+ } else {
+ return Cat not found;
+ }
+ };
+ // :replace-end:
+ // :snippet-end:
+
+ const App = () => (
+
+
+
+ );
+ const {getByTestId} = render();
+ const catBirthDate = await waitFor(() => getByTestId('catBirthDate'));
+ // Expect catBirthDate in the UI to be the same value we set in the beforeEach (which is clover's birthday 'January 21, 2016')
+ expect(new Date(catBirthDate.props.children)).toStrictEqual(
+ new Date('January 21, 2016'),
+ );
+ });
+});
diff --git a/examples/react-native/__tests__/ts/models/Cat.ts b/examples/react-native/__tests__/ts/models/Cat.ts
new file mode 100644
index 0000000000..63e299b30e
--- /dev/null
+++ b/examples/react-native/__tests__/ts/models/Cat.ts
@@ -0,0 +1,17 @@
+import Realm from 'realm';
+// TODO: Replace `static schema` with TS-first models + realm-babel-plugin (https://www.npmjs.com/package/@realm/babel-plugin) approach once realm-babel-plugin version 0.1.2 releases with bug fixes
+// :snippet-start: ts-cat-schema
+class Cat extends Realm.Object {
+ name!: string;
+ birthDate?: Realm.Mixed;
+
+ static schema = {
+ name: 'Cat',
+ properties: {
+ name: 'string',
+ birthDate: 'mixed',
+ },
+ };
+}
+// :snippet-end:
+export default Cat;
diff --git a/examples/react-native/__tests__/ts/realm-database/schemas/mixed-test.tsx b/examples/react-native/__tests__/ts/realm-database/schemas/mixed-test.tsx
new file mode 100644
index 0000000000..4139a8a929
--- /dev/null
+++ b/examples/react-native/__tests__/ts/realm-database/schemas/mixed-test.tsx
@@ -0,0 +1,149 @@
+import React, {useEffect} from 'react';
+import {Text, View} from 'react-native';
+import {render, waitFor} from '@testing-library/react-native';
+import Realm from 'realm';
+import {createRealmContext} from '@realm/react';
+import Cat from '../../models/Cat';
+
+jest.setTimeout(30000);
+
+const realmConfig = {
+ schema: [Cat],
+ deleteRealmIfMigrationNeeded: true,
+};
+
+const {RealmProvider, useRealm, useQuery} = createRealmContext(realmConfig);
+
+let assertionRealm: Realm;
+
+describe('Mixed Tests', () => {
+ beforeEach(async () => {
+ // we will use this Realm for assertions to access Realm Objects outside of a Functional Component (like required by @realm/react)
+ assertionRealm = await Realm.open(realmConfig);
+
+ // delete every object in the realmConfig in the Realm to make test idempotent
+ assertionRealm.write(() => {
+ assertionRealm.delete(assertionRealm.objects(Cat));
+
+ new Cat(assertionRealm, {
+ name: 'Clover',
+ birthDate: new Date('January 21, 2016'),
+ });
+ });
+ });
+ afterAll(() => {
+ if (!assertionRealm.isClosed) {
+ assertionRealm.close();
+ }
+ });
+ it('should create an object with a mixed value', async () => {
+ // :snippet-start: create-mixed-object
+ // :replace-start: {
+ // "terms": {
+ // " testID='catItem'": ""
+ // }
+ // }
+ const CreateCatsInput = () => {
+ const realm = useRealm();
+
+ useEffect(() => {
+ // Add data to the Realm when the component mounts
+ realm.write(() => {
+ // create a Cat with a birthDate value of type string
+ new Cat(realm, {
+ name: 'Euler',
+ birthDate: 'December 25th, 2017',
+ });
+ // create a Cat with a birthDate value of type date
+ new Cat(realm, {
+ name: 'Blaise',
+ birthDate: new Date('August 17, 2020'),
+ });
+
+ // create a Cat with a birthDate value of type int
+ new Cat(realm, {name: 'Euclid', birthDate: 10152021});
+
+ // create a Cat with a birthDate value of type null
+ new Cat(realm, {name: 'Pythagoras', birthDate: null});
+ });
+ }, []);
+
+ // retrieve all cats
+ const cats = useQuery(Cat);
+
+ return (
+ <>
+ {cats.map(cat => (
+
+ {cat.name}
+ {String(cat.birthDate)}
+
+ ))}
+ >
+ );
+ };
+ // :replace-end:
+ // :snippet-end:
+
+ const App = () => (
+
+
+
+ );
+
+ const {getAllByTestId} = render();
+
+ const catItems = await waitFor(() => getAllByTestId('catItem'), {
+ timeout: 5000,
+ });
+
+ // Test that 5 Cat Items have been added to the UI,
+ // and 5 matching Cat objects have been created in the assertionRealm
+ // (since there was already 1 cat object 'clover' created in the beforeEach)
+ // + the 4 new Cats
+ setTimeout(() => {
+ expect(catItems.length).toBe(5);
+ const cats = assertionRealm.objects(Cat);
+ expect(cats.length).toBe(5);
+ }, 5500);
+ });
+ it('should query for objects with a mixed value', async () => {
+ // :snippet-start: query-mixed-object
+ // :replace-start: {
+ // "terms": {
+ // " testID='catBirthDate'": ""
+ // }
+ // }
+ const CatInfoCard = ({catName}: {catName: string}) => {
+ // To query for the cat's birthDate, filter for their name to retrieve the realm object.
+ // Use dot notation to access the birthDate property.
+ const cat = useQuery(Cat).filtered(`name = '${catName}'`)[0];
+ const catBirthDate = cat.birthDate;
+
+ if (cat) {
+ return (
+ <>
+ {catName}
+ {String(catBirthDate)}
+ >
+ );
+ } else {
+ return Cat not found;
+ }
+ };
+ // :replace-end:
+ // :snippet-end:
+
+ const App = () => (
+
+
+
+ );
+ const {getByTestId} = render();
+ const catBirthDate = await waitFor(() => getByTestId('catBirthDate'));
+ // Expect catBirthDate in the UI to be the same value we set in the beforeEach (which is clover's birthday 'January 21, 2016')
+ expect(new Date(catBirthDate.props.children)).toStrictEqual(
+ new Date('January 21, 2016'),
+ );
+ });
+});
diff --git a/examples/react-native/testSetup.js b/examples/react-native/testSetup.js
index d60624c7c8..ff2f65729d 100644
--- a/examples/react-native/testSetup.js
+++ b/examples/react-native/testSetup.js
@@ -7,3 +7,5 @@ global.console = {
error: jest.fn(),
warn: jest.fn(),
};
+
+jest.setTimeout(30000);
diff --git a/source/examples/generated/react-native/js/Cat.snippet.js-cat-schema.js b/source/examples/generated/react-native/js/Cat.snippet.js-cat-schema.js
new file mode 100644
index 0000000000..7b323b3d6a
--- /dev/null
+++ b/source/examples/generated/react-native/js/Cat.snippet.js-cat-schema.js
@@ -0,0 +1,9 @@
+class Cat extends Realm.Object {
+ static schema = {
+ name: 'Cat',
+ properties: {
+ name: 'string',
+ birthDate: 'mixed',
+ },
+ };
+}
diff --git a/source/examples/generated/react-native/js/mixed-tests.snippet.create-mixed-object.jsx b/source/examples/generated/react-native/js/mixed-tests.snippet.create-mixed-object.jsx
new file mode 100644
index 0000000000..73f910be56
--- /dev/null
+++ b/source/examples/generated/react-native/js/mixed-tests.snippet.create-mixed-object.jsx
@@ -0,0 +1,39 @@
+const CreateCatsInput = () => {
+ const realm = useRealm();
+
+ useEffect(() => {
+ // Add data to the Realm when the component mounts
+ realm.write(() => {
+ // create a Cat with a birthDate value of type string
+ new Cat(realm, {
+ name: 'Euler',
+ birthDate: 'December 25th, 2017',
+ });
+ // create a Cat with a birthDate value of type date
+ new Cat(realm, {
+ name: 'Blaise',
+ birthDate: new Date('August 17, 2020'),
+ });
+
+ // create a Cat with a birthDate value of type int
+ new Cat(realm, {name: 'Euclid', birthDate: 10152021});
+
+ // create a Cat with a birthDate value of type null
+ new Cat(realm, {name: 'Pythagoras', birthDate: null});
+ });
+ }, []);
+
+ // retrieve all cats
+ const cats = useQuery(Cat);
+
+ return (
+ <>
+ {cats.map(cat => (
+
+ {cat.name}
+ {String(cat.birthDate)}
+
+ ))}
+ >
+ );
+};
diff --git a/source/examples/generated/react-native/js/mixed-tests.snippet.query-mixed-object.jsx b/source/examples/generated/react-native/js/mixed-tests.snippet.query-mixed-object.jsx
new file mode 100644
index 0000000000..aca8c8f71f
--- /dev/null
+++ b/source/examples/generated/react-native/js/mixed-tests.snippet.query-mixed-object.jsx
@@ -0,0 +1,17 @@
+const CatInfoCard = ({catName}) => {
+ // To query for the cat's birthDate, filter for their name to retrieve the realm object.
+ // Use dot notation to access the birthDate property.
+ const cat = useQuery(Cat).filtered(`name = '${catName}'`)[0];
+ const catBirthDate = cat.birthDate;
+
+ if (cat) {
+ return (
+ <>
+ {catName}
+ {String(catBirthDate)}
+ >
+ );
+ } else {
+ return Cat not found;
+ }
+};
diff --git a/source/examples/generated/react-native/ts/Cat.snippet.ts-cat-schema.ts b/source/examples/generated/react-native/ts/Cat.snippet.ts-cat-schema.ts
new file mode 100644
index 0000000000..4e79383336
--- /dev/null
+++ b/source/examples/generated/react-native/ts/Cat.snippet.ts-cat-schema.ts
@@ -0,0 +1,12 @@
+class Cat extends Realm.Object {
+ name!: string;
+ birthDate?: Realm.Mixed;
+
+ static schema = {
+ name: 'Cat',
+ properties: {
+ name: 'string',
+ birthDate: 'mixed',
+ },
+ };
+}
diff --git a/source/examples/generated/react-native/ts/mixed-test.snippet.create-mixed-object.tsx b/source/examples/generated/react-native/ts/mixed-test.snippet.create-mixed-object.tsx
new file mode 100644
index 0000000000..73f910be56
--- /dev/null
+++ b/source/examples/generated/react-native/ts/mixed-test.snippet.create-mixed-object.tsx
@@ -0,0 +1,39 @@
+const CreateCatsInput = () => {
+ const realm = useRealm();
+
+ useEffect(() => {
+ // Add data to the Realm when the component mounts
+ realm.write(() => {
+ // create a Cat with a birthDate value of type string
+ new Cat(realm, {
+ name: 'Euler',
+ birthDate: 'December 25th, 2017',
+ });
+ // create a Cat with a birthDate value of type date
+ new Cat(realm, {
+ name: 'Blaise',
+ birthDate: new Date('August 17, 2020'),
+ });
+
+ // create a Cat with a birthDate value of type int
+ new Cat(realm, {name: 'Euclid', birthDate: 10152021});
+
+ // create a Cat with a birthDate value of type null
+ new Cat(realm, {name: 'Pythagoras', birthDate: null});
+ });
+ }, []);
+
+ // retrieve all cats
+ const cats = useQuery(Cat);
+
+ return (
+ <>
+ {cats.map(cat => (
+
+ {cat.name}
+ {String(cat.birthDate)}
+
+ ))}
+ >
+ );
+};
diff --git a/source/examples/generated/react-native/ts/mixed-test.snippet.query-mixed-object.tsx b/source/examples/generated/react-native/ts/mixed-test.snippet.query-mixed-object.tsx
new file mode 100644
index 0000000000..eda7559b6c
--- /dev/null
+++ b/source/examples/generated/react-native/ts/mixed-test.snippet.query-mixed-object.tsx
@@ -0,0 +1,17 @@
+const CatInfoCard = ({catName}: {catName: string}) => {
+ // To query for the cat's birthDate, filter for their name to retrieve the realm object.
+ // Use dot notation to access the birthDate property.
+ const cat = useQuery(Cat).filtered(`name = '${catName}'`)[0];
+ const catBirthDate = cat.birthDate;
+
+ if (cat) {
+ return (
+ <>
+ {catName}
+ {String(catBirthDate)}
+ >
+ );
+ } else {
+ return Cat not found;
+ }
+};
diff --git a/source/sdk/react-native/realm-database/schemas/mixed.txt b/source/sdk/react-native/realm-database/schemas/mixed.txt
index 77e90dfaf8..659c1f5a82 100644
--- a/source/sdk/react-native/realm-database/schemas/mixed.txt
+++ b/source/sdk/react-native/realm-database/schemas/mixed.txt
@@ -6,22 +6,22 @@ Mixed - React Native SDK
.. contents:: On this page
:local:
:backlinks: none
- :depth: 2
+ :depth: 1
:class: singlecol
.. versionadded:: 10.5.0
Overview
--------
-The mixed data type is a realm property type that can hold any valid Realm data type except a collection.
-You can create collections (lists, sets, and dictionaries) of type ``mixed``, but a ``mixed`` itself
-cannot be a collection. Properties using the mixed data type can also hold null values.
+The mixed data type is a realm property type that can hold any valid Realm data
+type except a collection. You can create collections (lists, sets, and
+dictionaries) of type ``mixed``, but a ``mixed`` type itself cannot be a
+collection.
-.. note::
+The mixed data type is indexable, but you can't use it as a primary key.
- The mixed data type is indexable, but you can't use it as a primary key.
- Because null is a permitted value, you can't declare a Mixed property as
- optional.
+Properties using the mixed data type can also hold null values. You can't
+declare a Mixed property as optional.
Realm Object Models
-------------------
@@ -29,25 +29,95 @@ To :ref:`set a property of your object model
` as ``Mixed``, set the property's type to
"``mixed``".
-.. literalinclude:: /examples/generated/node/data-types.snippet.define-mixed-in-schema.js
- :language: javascript
+.. tabs-realm-languages::
+
+ .. tab::
+ :tabid: typescript
+
+ .. literalinclude:: /examples/generated/react-native/ts/Cat.snippet.ts-cat-schema.ts
+ :language: typescript
+
+ .. tab::
+ :tabid: javascript
+
+ .. literalinclude:: /examples/generated/react-native/js/Cat.snippet.js-cat-schema.js
+ :language: javascript
+
Create an Object With a Mixed Value
-----------------------------------
-Create an object with a mixed value by running the :js-sdk:`realm.create()
-` method within a write transaction.
+Create an object with a mixed value by using the :mdn:`new
+` operator within a :ref:`write
+transaction `.
+
+Example
+~~~~~~~
+
+In the following ``CreateCatsInput`` example, we create several ``Cat`` realm
+objects with a ``mixed`` type for the ``birthDate`` field.
+
+The ``CreateCatsInput`` component does the following:
+
+- Get access to the opened realm instance by calling the ``useRealm()`` hook.
+- Use React's `useEffect `__ hook to call an anonymous function only once by passing ``useEffect`` an `empty dependency array `__ as a second argument.
+- Within the anonymous function, we create four different ``Cat`` objects by using the ``new`` operator to create a new realm object within a write transaction. Each of the ``Cat`` objects uses a different data type for the ``birthDate`` property.
+- Use the ``useQuery()`` hook to retrieve all ``Cat`` objects.
+- `Map `__ through the cats to render a list of ``Text`` components displaying each cat's ``name`` and ``birthDate``.
+
+
+.. tabs-realm-languages::
-.. literalinclude:: /examples/generated/node/data-types.snippet.create-objects-with-mixed-values.js
- :language: javascript
+ .. tab::
+ :tabid: typescript
+
+ .. literalinclude:: /examples/generated/react-native/ts/mixed-test.snippet.create-mixed-object.tsx
+ :language: typescript
+ :emphasize-lines: 2, 6-23
+ :linenos:
+
+ .. tab::
+ :tabid: javascript
+
+ .. literalinclude:: /examples/generated/react-native/js/mixed-tests.snippet.create-mixed-object.jsx
+ :language: javascript
+ :emphasize-lines: 2, 6-23
+ :linenos:
Query for Objects with a Mixed Value
------------------------------------
-Query for objects with a mixed value by running the
+To query for objects with a mixed value, run the
:js-sdk:`Collection.filtered() ` method and
-passing in a :ref:`filter ` for a non-mixed field. You can
+pass in a :ref:`filter ` for a non-mixed field. You can
then print the value of the mixed property or the entire object itself.
-.. literalinclude:: /examples/generated/node/data-types.snippet.query-objects-with-mixed-values.js
- :language: javascript
+Example
+~~~~~~~
+
+In the following ``CatInfoCard`` example, we query for a ``Cat`` object using the
+cat's name.
+
+The ``CatInfoCard`` component does the following:
+
+- Get all ``Cat`` objects by passing the ``Cat`` class to the ``useQuery()`` hook, and then use ``filtered()`` to filter the results to receive only the cats whose names match the name passed as a prop. We then get the first matching cat and store it as a const variable.
+- Use dot notation to retrieve the mixed property, ``birthDate``.
+- Display the cat's name and birthdate in the render method if Realm finds the cat. If there is no cat that matches the name passed into the component as a prop, we render text that says "Cat not found".
+
+.. tabs-realm-languages::
+
+ .. tab::
+ :tabid: typescript
+
+ .. literalinclude:: /examples/generated/react-native/ts/mixed-test.snippet.query-mixed-object.tsx
+ :language: typescript
+ :emphasize-lines: 4-5
+ :linenos:
+
+ .. tab::
+ :tabid: javascript
+
+ .. literalinclude:: /examples/generated/react-native/js/mixed-tests.snippet.query-mixed-object.jsx
+ :language: javascript
+ :emphasize-lines: 4-5
+ :linenos: