Alperen ARICI
Alperen ARICI

Reputation: 213

Why is my function unintentionally executing two times?

I have a constructor, get method, componentDidMount and componentWillUnmount methods. I want to just listen for a scroll event and, according to that, call the get method. If the scroll is at the bottom of page, the get method is called one time. That's all. The first call, that is componentDidmount(), is working one time but when I scroll down, the get method is working two times. I don't want it to execute more than once.

This is my code:

constructor(props) {
        super(props);
        cursor = -1
        id = auth().currentUser.providerData[0].uid
        this.state = {
            hits: [],
            isLoading: false,
            over: false,
            firstCall: true
        };
        this.get = this.get.bind(this)
        this.handleScroll = this.handleScroll.bind(this)
    }
    get() {
        this.setState({ isLoading: true });
        fetch("/1.1/followers/list.json?user_id=" + id + "&cursor=" + cursor + "", {
            headers: {
                'Authorization': 'MyToken',
            }
        }).then(response => response.json())
            .then(data => {
                if (data.next_cursor == 0) {
                    this.setState({ isLoading: false })
                    this.setState({ over: true })
                } else {
                    this.setState({ hits: this.state.hits.concat(data.users), isLoading: false })
                    cursor = data.next_cursor
                    console.log(data.next_cursor)
                }
            }).catch(error => {
                return
            })

    }
    componentDidMount() {
        this.get()
        window.addEventListener('scroll', this.handleScroll);
    }
    componentWillUnmount() {
        window.removeEventListener('scroll', this.handleScroll);
    }
    handleScroll(event) {
        if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
            this.get()
        }
    }

And that is my console output.

1634251341094964000 ----> one time

1614497980820334000 ----> two time

1579177573029464600 ----> two time

. . .

They are coming from console.log(data.next_cursor) at the get function.

Upvotes: 0

Views: 284

Answers (1)

Brian S
Brian S

Reputation: 5785

Since it seems like the event gets fired multiple times by the window / scrollbar, you'll need to guard against duplicate calls in your code. There are many ways to do this, depending on the context and the requirements. Here are a couple options.

You could debounce the function call. This would be good if you just need to make sure it is only called once within a certain time window.

Another option is to use state, and theisLoading prop you've already defined:

get(){
    if(!this.state.isLoading){

       //use the setState callback param here so we don't run into async issues
       this.setState({isLoading: true}, () => {

          ... the rest of your logic ...

          //get is finished (either success or failure)
          this.setState({isLoading: false});
       }
    }
}

Upvotes: 1

Related Questions