admin管理员组

文章数量:1317898

Why am I getting this error?

Warning: Can't call setState (or forceUpdate) on an unmounted ponent. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the ponentWillUnmount method.

postAction.js

export const getPosts = () => db.ref('posts').once('value');

ponents:

constructor(props) {
  super(props);
  this.state = { posts: null };
}

ponentDidMount() {
  getPosts()
    .then(snapshot => {
      const result = snapshot.val();
      this.setState(() => ({ posts: result }));
    })
    .catch(error => {
      console.error(error);
    });
}

ponentWillUnmount() {
  this.setState({ posts: null });
}

render() {
  return (
    <div>
      <PostList posts={this.state.posts} />
    </div>
  );
}

Why am I getting this error?

Warning: Can't call setState (or forceUpdate) on an unmounted ponent. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the ponentWillUnmount method.

postAction.js

export const getPosts = () => db.ref('posts').once('value');

ponents:

constructor(props) {
  super(props);
  this.state = { posts: null };
}

ponentDidMount() {
  getPosts()
    .then(snapshot => {
      const result = snapshot.val();
      this.setState(() => ({ posts: result }));
    })
    .catch(error => {
      console.error(error);
    });
}

ponentWillUnmount() {
  this.setState({ posts: null });
}

render() {
  return (
    <div>
      <PostList posts={this.state.posts} />
    </div>
  );
}
Share Improve this question edited Jul 9, 2018 at 13:33 Tholle 113k22 gold badges208 silver badges197 bronze badges asked Jul 9, 2018 at 13:30 Bayram AkbuzBayram Akbuz 751 silver badge7 bronze badges 4
  • 1 unmounted ponent dont have state, no need to do that. React is already telling you this is a no-op – Rikin Commented Jul 9, 2018 at 13:34
  • You should not call this.setState in ponentWillUnmount. Does the warning disappear if you remove that? – Tholle Commented Jul 9, 2018 at 13:35
  • Hey you can read react lifecycle hooks docs on official website. It says when ponent is unmounting, no sort of state updation is done because ultimately that ponent's UI is being destroyed – Meet Zaveri Commented Jul 9, 2018 at 13:35
  • getPosts() is asynchronous method. That's the mistake. Thank you all. Thank you @nicolas-tower – Bayram Akbuz Commented Jul 9, 2018 at 14:03
Add a ment  | 

4 Answers 4

Reset to default 7

As others mentioned, the setState in ponentWillUnmount is unnecessary, but it should not be causing the error you're seeing. Instead, the likely culprit for that is this code:

ponentDidMount() {
  getPosts()
    .then(snapshot => {
      const result = snapshot.val();
      this.setState(() => ({ posts: result }));
    })
    .catch(error => {
      console.error(error);
    });
}

since getPosts() is asynchronous, it's possible that before it can resolve, the ponent has unmounted. You're not checking for this, and so the .then can end up running after the ponent has unmounted.

To handle that, you can set a flag in willUnmount, and check for that flag in the .then:

ponentDidMount() {
  getPosts()
    .then(snapshot => {
      if (this.isUnmounted) {
        return;
      }
      const result = snapshot.val();
      this.setState(() => ({ posts: result }));
    })
    .catch(error => {
      console.error(error);
    });
}

ponentWillUnmount() {
  this.isUnmounted = true;
}

React ponent's state is a local entity. Unmounted ponent dont have state, no need to do that. React is already telling you this is a no-op which means no-operation in tech speak. It means that you telling ponent to do something when its already destroyed.

https://reactjs/docs/react-ponent.html#ponentwillunmount

You should not call setState() in ponentWillUnmount() because the ponent will never be re-rendered. Once a ponent instance is unmounted, it will never be mounted again.

Remove this

ponentWillUnmount() {
  this.setState({ posts: null });
}

it's useless

From the doc:

You should not call setState() in ponentWillUnmount() because the ponent will never be re-rendered. Once a ponent instance is unmounted, it will never be mounted again.

https://reactjs/docs/react-ponent.html#ponentwillunmount

You can try this code:

constructor(props) {
  super(props);
  this.state = { posts: null };
}

_isMounted = false;
ponentDidMount() {
  this._isMounted = true;
  getPosts()
    .then(snapshot => {
      const result = snapshot.val();
      if(this._isMounted) { 
          this.setState(() => ({ posts: result }))
      }
    })
    .catch(error => {
      console.error(error);
    });
}

ponentWillUnmount() {
  this._isMounted = false;
  this.setState({ posts: null });
}

render() {
  return (
    <div>
      <PostList posts={this.state.posts} />
    </div>
  );
}

By using _isMounted, setState is called only if the ponent is mounted. the answer simply does a check to see if the ponent is mounted before setting the state.

本文标签: