realm-js: Cannot remove a result object's listener
Goals
I’m trying to update my UI based on changes in to a realm object, so I added a listener to the result that calls forceUpdate. This solution, while a little ugly since I don’t like calling forceUpdate, works correctly, but when I call removeListener on the collection, it still continues to call forceUpdate. I’ve also tried calling removeListener on the entire realm, as well as removeAllListeners on the result object and entire realm with no success.
I know its a no - op so it doesn’t affect the app, but it is a nuisance and I feel like there should be a correct way I haven’t found
Expected Results
the listener is removed correctly
Actual Results
it isn’t and a No-Op react native warning is thrown due to react trying to update an unmounted component
Steps to Reproduce
add a listener to a result object in componentWillMount and remove it in componentWillUnmount
Code Sample
In the file where i define my realm instance I have the following:
const listeners = [];
export function addFineGrainListener(objectName, filter, callback) {
const collection = realm.objects(objectName).filtered(filter);
collection.addListener(callback);
listeners.push({ objectName, filter, collection, callback });
}
export function removeFineGrainListener(objectName, filter) {
const listenerObject = listeners.find(
listener => listener.objectName === objectName && listener.filter === filter,
);
listenerObject.collection.removeListener(listenerObject.callback);
}
and my component has the following:
componentWillMount() {
addFineGrainListener(
'JournalEntry',
\`id ==[c] "${this.props.screenProps.noteId}"\`,
this.updateUIDueToRealmChange,
);
}
componentWillUnmount() {
removeFineGrainListener(
'JournalEntry',
\`id ==[c] "${this.props.screenProps.noteId}"\`,
);
}
updateUIDueToRealmChange = () => {
this.forceUpdate();
};
Version of Realm and Tooling
- Realm JS SDK Version: 2.1.1
- Node or React Native: RN 51.0
- Client OS & Version: IOS 11.2
- Which debugger for React Native: Default Chrome Debugger
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 3
- Comments: 32 (8 by maintainers)
removeAllListeners
does nothing as well on collections.@gunnigylfa Strange, the same happen to me, but it was my fault. This code of yours should work:
dogs.removeAllLIsteners()
can you do a test for me? Put the dog variavel initializeing globally like this:Updated for the 2.6.0 documentation
@kneth Maybe like this?
I think my problem has something to do with the way I was updating the component state in the function I assigned to the listener. I was fetching a new version of the objects and calling setState with those newly fetched items rather than using those passed to me via the callback. I’m not sure why that would be the case. I’m working on refactoring my code in order to make the new approach work for me. @FlaviooLima Thank you but I’m not sure if I can use this approach since I’m writing this in a type safe language which compiles to JS.
I will post an update of the problem here once I’m able to replicate with the new approach.
@andrew-wagner89 If you’re using redux you can do this hack:
Where wines is a reducer and tracking is a property you toggle on it. At least then even if it doesn’t get removed, you can intercept its non mounted call.