Use Change Listeners In Components - React Native SDK
Overview
A best practice is to copy Realm objects to your component's state. However, since Realm 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 change listener in your component and updating the state variable when that listener fires.
The Realm React Native SDK does not provide first class support for global state management systems like Redux.
Learn more about change listener APIs in the React to Changes documentation.
Failing to update copies of Realm objects leads to out-of-date data displayed in your UI as objects are deleted or changed.
To handle exceptions thrown from a change listener, wrap your addListener()
call
within a try...catch statement.
Procedure
- To keep your UI up-to-date with changes to underlying Realm objects, declare a state variable for your Realm objects using the useState() hook.
- Within the useEffect() hook, set the state variable to the initial value of your objects. Then declare a change listener on the Realm objects.
- Finally, return an anonymous cleanup function that you can use to remove the change listener and close the Realm. React.js will call this cleanup function when the component unmounts.
If you need to access Realm objects in other components further down the component tree, pass the state variable for your Realm object as a prop or use React Context.
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 open
a realm within a useEffect
function and
then set the tasks
state variable to the initial value of the tasks
stored in the Realm.
The developer registers a change listener to update the state variable when
changes to the tasks
have been made in the Realm 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 close the realm.
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]); try{ tasks.addListener(() => { // update state of tasks to the updated value setTasks([...tasks]); }); } catch (error) { console.error( `Unable to update the tasks' state, an exception was thrown within the change listener: ${error}` ); } 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 () => { // 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> ))} </> ); };