Search code examples
androidreact-nativenavigationrealmreact-native-navigation

Error in navigation after creating new Realm object


I'm using the react-native-navigation package as well as Realm in my project. My app has a realm object called Notebook that contains a list of Verse objects, which are another realm object.

The structure of the app is very simple, the first page shows a list of Notebooks and when one is selected, the app transitions to the second screen which is a list of Verses.

Here is my code to navigate from the notebook list to the verse list:

this.props.navigator.push({
  screen: 'com.beyersapps.biblebinderrn.verselist',
  title: notebook.name,
  passProps: {notebook: notebook},
  animated: true,
  animationType: 'fade',
  backButtonTitle: undefined,
  backButtonHidden: false
})

This navigation works fine and I can move back and forth between the two screens. My problem comes when I create a new Verse and add it to the Notebook. Here is my code that lives in the second screen to create a new Verse:

realm.write(() => {
  let newVerse = realm.create('Verse', {
    reference: 'Genesis 1:1',
    favorite: false,
    memorized: false,
    scripture: 'My favorite verse'
  });

  if (this.notebook != null) {
    this.notebook.verses.push(newVerse);
  }
});

This is where my problem starts. At this point, if I select the back button to go back to the list of Notebooks, then select a notebook again, I get this error:

Attempting to change value of a readonly property.

Exception in native call java.lang.RuntimeException: Error calling RCTEventEmitter.receiveTouches

at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
at android.os.Looper.loop(Looper.java:154)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:199)
at java.lang.Thread.run(Thread.java:761)
Caused by: com.facebook.jni.CppException: Exception calling object as function: TypeError: Attempting to change value of a readonly property.
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) 
at android.os.Handler.handleCallback(Handler.java:751) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31) 
at android.os.Looper.loop(Looper.java:154) 
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:199) 
at java.lang.Thread.run(Thread.java:761) 

There are a couple of things I can do to make this problem go away, but both make my app useless. Since they might help in determining the issue though I can either remove {notebook: notebook} from passProps when I navigate to the new screen (but then nothing shows on the Verse list screen since it does not know which Notebook was selected). Or, I can not add the newly created Verse to the selected Notebook (but then I can't add data).

Since these two changes are in two different components (Realm and react-native-navigation), I'm not sure which component is the source of the problem.


Solution

  • Objects passed as props (passProps) are frozen by React Native. Try changing:

    passProps: {notebook: notebook}
    

    to:

    passProps: {notebook: _.cloneDeep(notebook)}
    

    If you need to reflect changes to the notebook in the previous screen, I think you should do so through the store.

    Another option is to pass notebookId and get the correct notebook by id from state.