SpicyClubSauce
SpicyClubSauce

Reputation: 4256

React Native Error: Can only update a mounted or mounting component

I have a RN app where I'm reading in data from Firebase when a component mounts (a 'Favorites' screen), and setting it as the state for the Favorites component to then render.

But when I'm on another screen and add an item to the favorites database in firebase, I'm getting a yellow warning of:

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component.

This pops up when I add a new item that would then update the data in firebase.database().ref('userfavs').child(DeviceID). To be clear, the functionality doesn't seem broken and when I console log out the datalist array from the state, the new "favorited" item is added on there as expected..

class Favorites extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      datalist: []
    };
    this.favsRef = firebase.database().ref('userfavs').child(DeviceID);
  }
  listenForItems(favsRef) {
    favsRef.on('value', (snap) => {
      var items = [];
      snap.forEach((child) => {
         items.push(child.val()
          );
        });
      });
      this.setState({
        datalist: items
         });
     });
  }

  componentWillMount() {
    this.listenForItems(this.favsRef);
  }

  render() {
    console.log('state datalist:', this.state.datalist);
    ... }}

I don't really understand this error, because i've put the listenForItems call under componentWillMount, so whenever I navigate to the "Favorites" screen and this component loads, it pulls down the most recent data in Firebase.

Thanks!

Upvotes: 0

Views: 596

Answers (1)

eosterberg
eosterberg

Reputation: 1452

You´re probably adding a listener that keep your Favorites component in memory after it has unmounted.

According to the docs, there is a .off method for detaching the listener: https://firebase.google.com/docs/reference/js/firebase.database.Query#off

Solution would be something like:

class Favorites extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      datalist: []
    }
    this.favsRef = firebase.database().ref('userfavs').child(DeviceID);
    this.listen = snap => {
      const dataItems = snap.map(child => child.val())
      this.setState({dataItems})        
    }
  }

  componentDidMount() { this.favsRef.on('value', this.listen) }
  componentWillUnmount() { this.favsRef.off('value', this.listen) }

Upvotes: 1

Related Questions