Jamgreen
Jamgreen

Reputation: 11039

Fetching data in componentDidMount occurs in warning "Can only update a mounted or mounting component"

I fetch data in React Native with fetch(url, ...) in my componentDidMount() method.

So my class looks something like

class Posts extends Component {
  state = {
    posts: []
  };

  componentDidMount() {
    fetch('https://...').then(res => res.json()).then(res => {
      this.setState({ posts: res.posts });
    }
  }

  render() {
    return <FlatList data={this.state.posts} ... />;
  }
}

It worked fine all until I started using redux and redux-persist.

Now I get the warning Warning: Can only update a mounted or mounting component. ....

I don't understand why this is happening since it should be mounted if it's called in componentDidMount.

I am wondering if I need to abort fetching in componentWillUnmount or if I should actually fetch the data to the redux store instead of only storing the data temporarily in the 'local component'. When I open most other apps, it seems the data is already loaded when I open the app - is this due to very fast data retrieval or are they saving the data in a persisting store?

I have seen some projects where they use if (this.isMounted) { .. } inside componentDidMount, but as I understand the lifecycle of this method, the component would always have been mounted at this time. Also, it seems isMounted is deprecated.

What am I doing wrong? The issue only occurs when I start the app, so there's no problem if I navigate to another route and then back to this route.

Upvotes: 2

Views: 1010

Answers (1)

Moti Azu
Moti Azu

Reputation: 5442

Since fetch is async, the component might not be mounted when the data arrives. when the arrow functions inside your thens are being called, the component had already finished mounting and continued to rendering probably. This the nature of Promise.

You should make sure the component is still mounted when setting it's state, like this:

class Posts extends Component {
  state = {
    posts: []
  };

  componentDidMount() {
    this.mounted = true;
    fetch('https://...').then(res => res.json()).then(res => {
      if(this.mounted) this.setState({ posts: res.posts });
    }
  }

  componentWillUnmount() {
    this.mounted = false;
  }

  render() {
    return <FlatList data={this.state.posts} ... />;
  }
}

Upvotes: 3

Related Questions