1

When my component loads, I make a call to my webApi, which returns an array of clients. I need to load that array into state, which then renders my screen with a list of clients.

So, in my constructor, I create my default state.

export default class Clients extends Component {
    constructor(props) {
        super(props);
        this.state = {
            clients: [{
               id: null,
               username: null,
               name: null
           }]
       }

Then, I need to call my api as soon as possible, populate my state, so that my list can be displayed on screen. So I am putting the api call, and setState into my componentWillMount

componentWillMount() {
    const request = {
        method: 'GET',
        URL: `${Server.ApiURL}/api/admin/clients`
    };
    console.log('Calling fetch....', this.state);

    fetchData(request)
    .then((data) => {
        console.log("Data recieved!", data);
         this.setState(
                     { clients : data });
    });
}

My log line where I say 'Data is recieved' shows the data as I'd expect in the console. An array of objects that match the objects I defined in my state.

However, I get an error when I attempt to setState.

Warning: Can't call setState (or forceUpdate) 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 the componentWillUnmount method.

I'm sure I have done this before. But am not sure why I am getting that error. Is the way I am attempting to populate state incorrect?

My thinking is I set the initial state of the state in the constructor, and then populate my data in componentWillMount.

Why am I getting the error, and how should I be achieving this?

5
  • seems like your component gets unmounted before it finishes the request. Try to put console.log in componentWillUnmount to see if that's true. Commented Jun 2, 2018 at 10:28
  • 2
    btw. componentWillMount is deprecated and its bets to start api calls in componentDidMount Commented Jun 2, 2018 at 10:29
  • I added componentDidMount and logged. It only gets called when I switch to another route. Commented Jun 2, 2018 at 10:31
  • If you do not switch to the another route do you get this warning? Commented Jun 2, 2018 at 10:32
  • No. But I've notice the state is being set, as if I render a property in my render method... I see the value update to a correct value from the state. So state is being set... But, this error appears still. Sometime it doesn't appear, which is strange. Commented Jun 2, 2018 at 10:34

1 Answer 1

2

The error means that you have somewhere (in a Promise callback) a reference to the Object (Clients component) that has been removed from react tree and should be garbage collected. But you still keep that reference making it vulnerable to memory leaks.

This happens when you navigate to another route.

  1. you start fetching
  2. navigate around and component gets unmounted (while request still pending)
  3. request comes back and tries to update state on a component that is no longer in react tree - you hold a reference to a "dead" component.

This is why it's recommended to keep your components side-effects free and move your async stuff somewhere else like redux-middleware.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.