0

I wonder if anyone knows how to fix this. I have 2 functions in my javascript and I make sure to bind both. Would appreciate it if anyone knows what unmounted component means and what possibly caused this. Is there anything wrong with how I structure my promises? It looks fine when I rendered my site locally.

Thank you!

E       AssertionError: Error in browser console:
E       webpack:///./node_modules/react-dom/cjs/react-dom.development.js? 178:25 "Warning: Can't
 perform a React state update on an unmounted component. This is a no-op, but it indicates a 
memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in 
%s.%s" "the componentWillUnmount method" "\n    in Likes (created by Post)"

my code:

import React from 'react';
import PropTypes from 'prop-types';

class Likes extends React.Component {
  /* Display number of likes a like/unlike button for one post
   * Reference on forms https://facebook.github.io/react/docs/forms.html
   */

  constructor(props) {
    super(props);
    this.state = { num_likes: 0, logname_likes_this: false };
    this.like = this.like.bind(this);
    this.unlike = this.unlike.bind(this);
  }

  componentDidMount() {
    fetch(this.props.url, { credentials: 'same-origin' })
    .then((response) => {
      if (!response.ok) throw Error(response.statusText);
      return response.json();
    })
    .then((data) => {
      console.log(data)
      this.setState({
        num_likes: data.likes_count,
        logname_likes_this: data.logname_likes_this,
      });
    })
    .catch(error => console.log(error));
  }

  like(event) {
    event.preventDefault();
    fetch(this.props.url, {
      method: "POST",
      header: {
        'Content-Type': 'application/json'
      },
    })
    .then(()=>{
      this.setState({
        num_likes: this.state.num_likes + 1,
        logname_likes_this: 1,
      })
    })
    .catch(error => console.log(error));
  }

  unlike(event) {
    event.preventDefault();
    fetch(this.props.url, {
      method: "DELETE",
      header: {
        'Content-Type': 'application/json'
      },
    })
    .then(()=>{
      this.setState({
        num_likes: this.state.num_likes - 1,
        logname_likes_this: 0,
      })
    })
    .catch(error => console.log(error));
  }

  render() {
    let button; 

    if (this.state.logname_likes_this) {
      button = <button onClick={this.unlike} className="like-unlike-button">unlike</button>
    } else {
      button = <button onClick={this.like} className="like-unlike-button">like</button>
    }
    return (
      <div className="likes">
        <p>{this.state.num_likes} like{this.state.num_likes !== 1 ? 's' : ''}</p>
        {button}
      </div>
    );
  }
}

Likes.propTypes = {
  url: PropTypes.string.isRequired,
};

export default Likes;
Erin
  • 83
  • 1
  • 9
  • 1
    This means that the `Likes` component gets unmounted while one of the `fetches` is in progress. So when the `fetch` completes the code tries to `setState` but `this` refers to the unmounted component. – Gabriele Petrioli Feb 15 '20 at 22:28
  • thank you! but I thought I bind both functions (like and unlike). How can I keep the component mounted? – Erin Feb 15 '20 at 23:27
  • That depends on the code that mounts the `Likes` component. The binding has nothing to do with the problem here. The parent component needs to either not unmount the `Likes` or the `Likes` need to cancel the fetch in the `componentWillUnmount` lifecycle method (*or skip the state update if unmounted*). – Gabriele Petrioli Feb 15 '20 at 23:50
  • See https://stackoverflow.com/a/56537704/128165 – Gabriele Petrioli Feb 15 '20 at 23:57
  • Hey, take a look at this thread, it's well explained and to me it seems like this is the solution you're looking for: https://stackoverflow.com/questions/49906437/how-to-cancel-a-fetch-on-componentwillunmount – LetItBeAndre Feb 16 '20 at 12:07

0 Answers0