EyalS
EyalS

Reputation: 1692

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;

Upvotes: 10

Views: 9239

Answers (4)

Mateus Degobi
Mateus Degobi

Reputation: 21

This is work for me:

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

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

}

Upvotes: 0

Hải Anh Nguyễn
Hải Anh Nguyễn

Reputation: 163

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

Upvotes: 0

Alish Giri
Alish Giri

Reputation: 2238

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

Upvotes: 3

EyalS
EyalS

Reputation: 1692

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

Upvotes: 7

Related Questions