Pierre Ftn
Pierre Ftn

Reputation: 331

How to setState in ComponentDidMount

I have something strange with a react app,

I used it in a django project and want to re-use it in a laravel project but it doesn't want to work properly ...

Here is the code of my component :

import React from "react"
import {LeftControl, RightControl, CountControl } from './controls'
import {Slide} from './slide'
import axios from "axios"

export default class Slider extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            items : [],
            active:0
        }
     }

componentDidMount() {
    axios.get('/coming')
        .then((res)=>{
            this.setState({ items: res.data, active: 0})
        });
    setInterval( () => {
        this.goToNextSlide()
    },5000);
}

goToPrevSlide = () => {
    const n = this.state.items.length
    if (this.state.active == 0) {
        this.setState({active : n-1})
    } else {
        this.setState({active: this.state.active - 1})
    }
}

goToNextSlide = () => {
    const n = this.state.items.length
    if (this.state.active == n-1){
        this.setState({active : 0})
    } else {
        this.setState({active: this.state.active +1})
    }
}

render(){
    return(
        <div className="slider">
            <div className="slider__controls">
                <CountControl active={this.state.active} length={this.state.items.length} />
                <LeftControl goToPrevSlide={this.goToPrevSlide} />
                <RightControl goToNextSlide={this.goToNextSlide}/>
            </div>
            <div className="slider__items">
                {
                    this.state.items
                        .map((item, i) => (
                            <Slide active={this.state.active} index={i} key={i} id={item.id} first_name={item.first_name} last_name={item.last_name} role={item.role} conference_date={item.conference_date} thumbnail={item.thumbnail} />
                        ))
                }
            </div>
        </div>
    )
}

}

Uncommenting the setState in componentDidMount raise the following error :

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 the componentWillUnmount method.
in Slider

The component works well on my other project ...

Anyone would have an idea what is the problem ?

Thank you

Upvotes: 0

Views: 2403

Answers (1)

nebuler
nebuler

Reputation: 1545

As riwu commented, you get the warning because the axios call and timer you define in componentDidMount try to set the state of Slider after it has been unmounted. Do the following instead:

export default class Slider extends React.Component {
    ...

    constructor(props) {
        super(props);
        this._isMounted = false;
        this.state = {
            items : [],
            active:0,
        }
    }

    componentDidMount() {
        this._isMounted = true;

        axios.get('/coming')
            .then((res) => {
                if (this._isMounted) {
                    this.setState({ items: res.data, active: 0})
                }
            });

        this.timer = setInterval(() => {
            this.goToNextSlide();
        }, 5000);
    }

    componentWillUnmount() {
        this._isMounted = false;
        clearInterval(this.timer);
    }

    ...
}

Upvotes: 2

Related Questions