'realm.js - Accessing object of type Contact which has been invalidated or deleted with NO stack trace

Would (really) appreciate help on this one.
I have a realm listView which navigates away to a detailed view.
The detailed view is deleting the entry from the original list view and navigate back. I have registered listeners on the realm DB change to update the content of the list view.
Here is the code I'm using, which, after delete get an exception - "Accessing object of type Contact which has been invalidated or deleted" after the navigation occurs.
Does anyone have an idea why?
Also, it seems that the change listener (updateContactsFromDB) is called twice, while deleting just one object - ideas?

10x

ContactPage.js:

export default class ContactsPage extends Component {
  updateContactsFromDB(){
    console.log("ContactsPage:updateContactsFromDB()");
    let contacts = Realm.objects('Contact');
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(contacts.snapshot()),
    });
  }
  constructor(props) {
    console.log("ContactsPage:constructor()");
    super(props);
    const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => (r1 !== r2)});
    let contacts = Realm.objects('Contact');
    this.state = {
      dataSource: ds.cloneWithRows(contacts.snapshot()),
    };
     this.updateContactsFromDB = this.updateContactsFromDB.bind(this);
  }
  componentWillMount(props){
    console.log("ContactsPage:componentWillMount");
    Realm.addListener('change', this.updateContactsFromDB);
  }
  componentWillUnmount(props){
    console.log("ContactsPage:componentWillUnmount");
    Realm.removeListener('change', this.updateContactsFromDB);
  }
  render() {
    console.log("ContactsPage:render()");
    return (
            <ListView
              dataSource={this.state.dataSource}
              renderRow={(contact) => (
                <TouchableOpacity onPress={ () => this.props.navigation.navigate('ContactNotesPage', { contact: contact}) }>
                  <Text>test Contact</Text>
                </TouchableOpacity>
              )
            }
            />
    );
  }
}

ContactNotesPage.js:

export default class ContactNotesPage extends Component {
  constructor(props) {
    console.log("ContactNotesPage:constructor");
    super(props);
  }
  render(){
    console.log("ContactNotesPage:render()");
    const { params } = this.props.navigation.state;
    return (
      <TouchableOpacity onPress={ () => {
          console.log("ContactNotesPage:delete");
            Realm.write(() => { Realm.delete(params.contact);});
            this.props.navigation.navigate('ContactsPage');
        }
       }>
      <Text>DeleteContact</Text>
      </TouchableOpacity>
    )
  }
};

// main.js
const MainStack = StackNavigator({
  ContactsPage: {
    screen: ContactsPage,
  },
  ContactNotesPage:{
    screen: ContactNotesPage,
  },
});

export default MainStack;


Solution 1:[1]

Seems like it's a bug in realm/react-navigation. when passing a parameter which is a realm object - if you delete this object your next navigation will fail. A bug is already open at https://github.com/realm/realm-js/issues/1031

Solution 2:[2]

This happens when you get an object from realm (using realm.objects('collection')) and use realm.close() function on it. Either use Object.assign method or destructuring object or array approach to mitigate this problem. Like below,

const realmObject = realm.objects('collection');
const obj = [...realmObject] or {...realmObject[0]}; // the later one when filtered is used on realmObject.

My solution was that I did not call realm.close() because I was constantly engaged with the database.

https://realm.io/docs/javascript/0.14.0/api/Realm.html#close

Solution 3:[3]

i used useFocusEffect from @react-navigation/native after delete item in array for update list array like this

//state to check get data ability: 

 const [getDataAbility, setGetDataAbility] = useState(true);        
  //useFocusEffect

   useFocusEffect(
      React.useCallback(() => {
           if (getDataAbility === true) {
            // handle data
           }
      }, [ dependencies... ]),
   );
 // catch error ""accessing obj of..."
 try {
       console.log(pickingItem.id);
   } catch (error) {
    setGetDataAbility(false);
    console.log('err picking: ', error);
   }

-> solve

Solution 4:[4]

This is work for me:

async function updateRealm() {
  const realm = Realm.open({
    schemas: [
      /*myschemas*/
    ]
  });

    realm.addListener('change', () => {
      /* consult function */
    });

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 EyalS
Solution 2
Solution 3
Solution 4 Mateus Degobi