React-native-background-geolocation: How to remove listener(component) when activity is destroyed(component is unmounted)

Created on 3 Jun 2017  路  3Comments  路  Source: mauron85/react-native-background-geolocation

Now I get no-op warning, that it can update only mounted component, every time when I get new location. It should be memory leak of older component. Because, it happening after re-entering to the app.
How to remove references to this component in method componentWillUnmount?

question

Most helpful comment

Yep, if you configure event listeners in component that can be unmounted, make sure you unsubscribe from events in componentWillUnmount. But I would say it is better to register events in component that never get unmounted (eg. root component). Or even better register listeners outside of any component in index.*.js and use redux/flux actions to propagate data as props into your components.

If you insists on registering listener in component that can get unmounted, you can unregister listeners like this:

Solution 1

const unsubscribe = BackgroundGeolocation.on('location', (location) => {...})
//
unsubscribe();

Solution 2

remove all listeners with:

BackgroundGeolocation.removeAllListeners

*also check sample app in next branch https://github.com/mauron85/react-native-background-geolocation-example/blob/next/src/common/scenes/MainScene.js#L135

Prefered solution (redux + LocationManager)

LocationManager.js (code not tested!)

const LOCATION_UPDATE = 'LOCATION_UPDATE';

let store = null;

const listen = (currentStore, config) => {
  store = currentStore;
  BackgroundGeolocation.configure(config);
  BackgroundGeolocation.on('location', (location) => {
    store.dispatch({ type: LOCATION_UPDATE, payload: location });
  });
};
const start = () => {
  BackgroundGeolocation.start();
};

const stop = () => {
  BackgroundGeolocation.stop();
};

export default { listen, start, stop };

in your index.*.js

import LocationManager from './LocationManager';

const bgConfig = {}; // BackgroundGeolocation configuration
const store = configureStore(); // configure REDUX store
LocationManager.listen(store, bgConfig);

// render main component and other stuff
...

Now you can start and stop LocationManager from any component via LocationManager.start() or LocationManager.stop() without worrying about memory leaks.

You can listen to LOCATION_UPDATE action in redux reducer or redux saga, etc.

All 3 comments

Deeper debugging shows that module is not unregistering the emitter. So component is leaking, but native (android) module doesn't

Yep, if you configure event listeners in component that can be unmounted, make sure you unsubscribe from events in componentWillUnmount. But I would say it is better to register events in component that never get unmounted (eg. root component). Or even better register listeners outside of any component in index.*.js and use redux/flux actions to propagate data as props into your components.

If you insists on registering listener in component that can get unmounted, you can unregister listeners like this:

Solution 1

const unsubscribe = BackgroundGeolocation.on('location', (location) => {...})
//
unsubscribe();

Solution 2

remove all listeners with:

BackgroundGeolocation.removeAllListeners

*also check sample app in next branch https://github.com/mauron85/react-native-background-geolocation-example/blob/next/src/common/scenes/MainScene.js#L135

Prefered solution (redux + LocationManager)

LocationManager.js (code not tested!)

const LOCATION_UPDATE = 'LOCATION_UPDATE';

let store = null;

const listen = (currentStore, config) => {
  store = currentStore;
  BackgroundGeolocation.configure(config);
  BackgroundGeolocation.on('location', (location) => {
    store.dispatch({ type: LOCATION_UPDATE, payload: location });
  });
};
const start = () => {
  BackgroundGeolocation.start();
};

const stop = () => {
  BackgroundGeolocation.stop();
};

export default { listen, start, stop };

in your index.*.js

import LocationManager from './LocationManager';

const bgConfig = {}; // BackgroundGeolocation configuration
const store = configureStore(); // configure REDUX store
LocationManager.listen(store, bgConfig);

// render main component and other stuff
...

Now you can start and stop LocationManager from any component via LocationManager.start() or LocationManager.stop() without worrying about memory leaks.

You can listen to LOCATION_UPDATE action in redux reducer or redux saga, etc.

I think this is can be considered as resolved

Was this page helpful?
0 / 5 - 0 ratings