Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using setState in every iteration of a loop bad practice?

Here is a little code snippet:

async componentDidMount() {
    ...
    this.state.postList.forEach(element => {
      this.fetchItem(element);
    });
}

async fetchItem(query) {
    ...
    this.setState( previousState => {
        const list = [...previousState.data, data];
        return { data: list };
    });
}

I'm curious to know if using setState in every iteration of a forEach loop is a bad idea or not. I'm suspecting that it impacts performance, but I'd like to know for sure because this seemed like the simplest solution to this problem.

like image 900
MatijaxD Avatar asked Sep 24 '19 16:09

MatijaxD


People also ask

Can you use setState in a loop?

setState() will always lead to a re-render unless shouldComponentUpdate() returns false . To avoid unnecessary renders, calling setState() only when the new state differs from the previous state makes sense and can avoid calling setState() in an infinite loop within certain lifecycle methods like componentDidUpdate .

Can we set state without using setState?

Yes, but you might not want to. With class components we would keep all of our state in one object. Then when we changed state with setState , we would provide an object and the API would "merge" its contents into the existing state for us. This doesn't happen with setting state in function components with useState .

Does setState happen immediately?

setState() does not immediately mutate this. state but creates a pending state transition. Accessing this. state after calling this method can potentially return the existing value.

What happens when you call setState?

The setState() schedule changes to the component's state object and tells React that the component and its children must rerender with the updated state: // Correct this.


1 Answers

Here's an alternative approach: Update your fetchItem to just return the item. In your componentDidMount use Promise.all to get all the items and then commit them to the state in a single operation.

async componentDidMount() {
    const items = await Promise.all(this.state.postList.map(element => fetchItem(element)));
    this.setState({data: items});
}

async fetchItem(query) {
    const item = await getItem(query) // however you accomplish this
    return item;
}
like image 84
Arash Motamedi Avatar answered Sep 18 '22 20:09

Arash Motamedi