Skip to content

(DOCSP-15010): Using Change Listeners In Your Components - React Native SDK #996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d3b0c29
(DOCSP-15010): Reacting to changes from components
Apr 20, 2021
e37787f
removed unneeded text
Apr 20, 2021
2b94412
update
Apr 21, 2021
fdd9167
add instructions to class components
Apr 21, 2021
e8acbd3
separated react content from react-to-changes
Apr 21, 2021
c442b18
added rn files to its own examples folder under node + excluded them …
Apr 22, 2021
eca304b
fix file names
Apr 22, 2021
f7f7745
added generated files
Apr 22, 2021
f116dc0
Add emphasize lines
Apr 22, 2021
968bac4
fix conflicts
Apr 22, 2021
c37ac63
re-add class component
Apr 22, 2021
6d0b62a
re-add functional component
Apr 22, 2021
f877c51
fix toc tree
Apr 22, 2021
c47c681
update wording
Apr 22, 2021
2e78747
fix grammar
Apr 22, 2021
88ec793
updated title to avoid gerunds
Apr 22, 2021
ade339d
fix typo our->your
Apr 27, 2021
a2b780d
replace {+realm+} objects with {+service-short+} objects
Apr 27, 2021
72cfe5a
fix wording
Apr 27, 2021
a2a70bc
update
Apr 27, 2021
c50fbaf
removed redudant class component example
Apr 27, 2021
4e17453
Update source/sdk/react-native/examples/react-to-changes.txt
Apr 27, 2021
9d67128
fix spacing
Apr 27, 2021
616781b
fixed Reactjs -> React.js
Apr 27, 2021
c474a46
update wording
Apr 27, 2021
32000ae
typo fix
Apr 27, 2021
bcd40ae
update wording
Apr 27, 2021
64a99dc
switched component name
Apr 27, 2021
af8bfcf
add example directive
Apr 27, 2021
2ee9860
fix example paragraph
Apr 27, 2021
0e20a70
fix wording and grammar
Apr 27, 2021
33fdb0b
fix grammar
Apr 27, 2021
8e74475
fix typo
Apr 28, 2021
1e42590
Update source/sdk/react-native/examples/use-change-listeners-in-compo…
Apr 29, 2021
66c19bf
Update source/sdk/react-native/examples/use-change-listeners-in-compo…
Apr 29, 2021
a5c2006
Update source/sdk/react-native/examples/use-change-listeners-in-compo…
Apr 29, 2021
81e103d
added emphasize to non-generated file
Apr 29, 2021
da929b3
switched literalinclude to include for rst formatting
Apr 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, {useEffect, useState} from 'react';
import {Text} from 'react-native';
import Realm from 'realm';
// :code-block-start: using-change-listeners-functional-component
const TaskList = () => {
const [tasks, setTasks] = useState([]);
// :emphasize-start:
useEffect(() => {
// :emphasize-end:
Realm.open({
schema: [TaskSchema], // predefined schema
}).then(realm => {

const tasks = realm.objects('Task');
// set state to the initial value of your realm objects
setTasks([...tasks]);

// :emphasize-start:
tasks.addListener(() => {
// update state of tasks to the updated value
setTasks([...tasks]);
});
// :emphasize-end:

realm.write(() => {
// the following tasks will trigger the change listener and update the UI
realm.create('Task', {
name: 'Go to the grocery store',
});
realm.create('Task', {
name: 'Exercise in the gym',
});
});

// cleanup function
// :emphasize-start:
return () => {
const tasks = realm.objects('Task');
// Remember to remove the listener when you're done!
tasks.removeAllListeners();
// :emphasize-end:
// Call the close() method when done with a realm instance to avoid memory leaks.
realm.close();
};
});
}, []);

return (
<>
{tasks.map(task => (
<Text key={task.name}>{task.name}</Text>
))}
</>
);
};
// :code-block-end:
export default TaskList;
30 changes: 12 additions & 18 deletions examples/node/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,21 @@ module.exports = {
projects: [
{
displayName: "JavaScript",
moduleFileExtensions: ['js'],
testMatch: [
"<rootDir>/Examples/**/*.js",
],
setupFilesAfterEnv: [
'<rootDir>/testSetup.js',
],
moduleFileExtensions: ["js"],
testMatch: ["<rootDir>/Examples/**/*.js"],
setupFilesAfterEnv: ["<rootDir>/testSetup.js"],
modulePathIgnorePatterns: ["<rootDir>/Examples/rn"],
},
{
displayName: "TypeScript",
moduleFileExtensions: ['ts', 'js'],
preset: 'ts-jest/presets/js-with-ts',
setupFilesAfterEnv: [
'<rootDir>/testSetup.js',
],
testMatch: [
"<rootDir>/Examples/**/*.ts",
],
"transform": {
"^.+\\.ts$": "ts-jest"
moduleFileExtensions: ["ts", "js"],
preset: "ts-jest/presets/js-with-ts",
setupFilesAfterEnv: ["<rootDir>/testSetup.js"],
modulePathIgnorePatterns: ["<rootDir>/Examples/rn"],
testMatch: ["<rootDir>/Examples/**/*.ts"],
transform: {
"^.+\\.ts$": "ts-jest",
},
},
]
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.. code-block:: javascript
:emphasize-lines: 3, 12-15, 28-31

const TaskList = () => {
const [tasks, setTasks] = useState([]);
useEffect(() => {
Realm.open({
schema: [TaskSchema], // predefined schema
}).then(realm => {

const tasks = realm.objects('Task');
// set state to the initial value of your realm objects
setTasks([...tasks]);

tasks.addListener(() => {
// update state of tasks to the updated value
setTasks([...tasks]);
});

realm.write(() => {
// the following tasks will trigger the change listener and update the UI
realm.create('Task', {
name: 'Go to the grocery store',
});
realm.create('Task', {
name: 'Exercise in the gym',
});
});

// cleanup function
return () => {
const tasks = realm.objects('Task');
// Remember to remove the listener when you're done!
tasks.removeAllListeners();
// Call the close() method when done with a realm instance to avoid memory leaks.
realm.close();
};
});
}, []);

return (
<>
{tasks.map(task => (
<Text key={task.name}>{task.name}</Text>
))}
</>
);
};
2 changes: 2 additions & 0 deletions source/sdk/react-native/examples.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Usage Examples - React Native SDK
Open & Close a Local Realm </sdk/react-native/examples/open-and-close-a-local-realm>
Read & Write Data </sdk/react-native/examples/read-and-write-data>
React to Changes </sdk/react-native/examples/react-to-changes>
Use Change Listeners In Components </sdk/react-native/examples/use-change-listeners-in-components>
Modify an Object Schema </sdk/react-native/examples/modify-an-object-schema>
Connect to a MongoDB Realm Backend App </sdk/react-native/examples/connect-to-mongodb-realm-backend-app>
Authenticate Users </sdk/react-native/examples/authenticate-users>
Expand All @@ -26,6 +27,7 @@ Realm-Database (Non-Sync)
- :doc:`Open & Close a Local Realm </sdk/react-native/examples/open-and-close-a-local-realm>`
- :doc:`Read & Write Data </sdk/react-native/examples/read-and-write-data>`
- :doc:`React to Changes </sdk/react-native/examples/react-to-changes>`
- :doc:`Use Change Listeners In Components </sdk/react-native/examples/use-change-listeners-in-components>`
- :doc:`Modify an Object Schema </sdk/react-native/examples/modify-an-object-schema>`

Application Services (Sync)
Expand Down
7 changes: 6 additions & 1 deletion source/sdk/react-native/examples/react-to-changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,9 @@ call the instance's ``removeAllListeners()`` function:
- :js-sdk:`Realm.Object.removeAllListeners() <Realm.Object.html#removeAllListeners>`

.. literalinclude:: /examples/generated/node/react-to-changes.codeblock.react-to-changes-remove-all-listeners.js
:language: javascript
:language: javascript

Registering and Removing Listeners From Your React Components
-------------------------------------------------------------
To learn how to register and remove listeners within your application, check out
the documentation on how to :ref:`use change listeners in React components <react-native-use-listeners-in-components>`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
.. _react-native-use-listeners-in-components:

=====================================================
Use Change Listeners In Components - React Native SDK
=====================================================

.. default-domain:: mongodb

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol


Overview
--------
You can copy your {+service-short+} objects to your component's :reactjs:`state
<docs/state-and-lifecycle.html>`. However, since {+service-short+} objects are
live and automatically update in response to changes, you must update the copies
of them to prevent your UI from drifting out of date with underlying data. You can do this by
registering a :ref:`change listener <react-native-change-notifications>` in your
component and updating the state variable when that listener fires.

.. warning::

Failing to update copies of {+service-short+} objects leads to out-of-date data displayed
in your UI as objects are deleted or changed.

Procedure
~~~~~~~~~
To keep your UI up-to-date with changes to underlying {+service-short+} objects,
declare a state variable for your {+service-short+} objects using the
:reactjs:`useState() <docs/hooks-state.html>` hook.

Within the :reactjs:`useEffect() <docs/hooks-effect.html>` hook, set the state variable to
the initial value of your objects. Then declare a change listener on the
{+service-short+} objects.

Finally, return an anonymous cleanup function that you can use to remove the
change listener and close the {+service-short+}. React.js will call this cleanup function when
the component unmounts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to above, I think we're missing the why of this paragraph. I understand that we need to clean up the listener when we're done displaying the object on the UI and no longer need the listener... but that might not be obvious to a reader who's just learning about realm. Also, should "Reactjs" be "ReactJS" or "React.js" or even just "React"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Good catch, altered Reactjs to be 'React.js' (proper term is either 'React.js' or 'ReactJS' 👍
  • Also, remember that this is a usage example. Like the other usage examples, this presents a procedure without delving into the why. To learn the why, a user should have read/can read: React Native SDK > Fundamentals > Change Notifications


.. example::

In the following example, a developer creates an application to manage
tasks. Within a ``TaskList`` component, define a state variable called
``tasks``. The developer wants to display the initial list of tasks already
saved in the database after the component mounts. To do this, they :ref:`open
a realm <react-native-open-a-local-realm>` within a ``useEffect`` function and
then set the ``tasks`` state variable to the initial value of the ``tasks``
stored in the {+service-short+}.

The developer registers a change listener to update the state variable when
changes to the ``tasks`` have been made in the {+client-database+}. The
developer then creates some additional tasks.

Once the component unmounts, the developer wants to unregister the change
listener. To do this, they return a cleanup function and call ``task.removeAllListeners()``.
Finally they :ref:`close the realm <react-native-close-a-realm>`.

.. include:: /examples/generated/rn/using-change-listeners-functional-component.codeblock.using-change-listeners-functional-component.js.code-block.rst