0

I am totally confused about what's happening here. I am setting the state in React but it's updating very late. Here is the function:

fetchTimesheets() {
    const userId = cryptInfo.decrypt(localStorage.getItem('user_id'))
    var userArray = []
    var timeSheets = []
    fetchManagerProject(userId)
      .then(async (res) => {
        const projects = await res.json()
        projects.forEach(project => {
          project.teammember && project.teammember.forEach(member => {
            if (userArray.indexOf(member.user) === -1) {
              userArray.push(member.user)
              fetchUserTimelogs(member.user)
                .then(async (res) => {
                  const timesheet = await res.json()
                  if (timesheet)
                    timesheet.forEach(sheet => {
                      timeSheets.push(sheet)
                    });
                })
            }
          })
        })
        
        this.setState({
          timesheets: timeSheets
        })
      })

  }
     

I am calling this function on componentDidMount method

componentDidMount() {
    this.fetchTimesheets()
}

But I am getting that my value is evaluated just now and state is not updated. I have seen many questions related to this but didn't get a good solution.

halfer
  • 19,824
  • 17
  • 99
  • 186
Adesh Kumar
  • 952
  • 2
  • 16
  • 33
  • The timeSheet array is not empty when updating the state? – Tiisetso Tjabane Aug 21 '19 at 10:24
  • 1
    Does this answer your question? [console.log is not showing correct values](https://stackoverflow.com/questions/50577190/console-log-is-not-showing-correct-values) – Zach Aug 18 '20 at 17:39

2 Answers2

1

Have you checked to see whether it is the requests that you are making that are taking a long time or whether it's the setState itself?

Your fetchTimesheets contains multiple http requests on a loop (forEach) which could take some time to complete depending on the request. Because the forEach loop is a blocking function it means that your setState function will not be called until the forEach functions execution has completed.

To speed this up, you could consider setting the timesheet in-state each time you get a new timesheet. For example

fetchManagerProject(userId)
    .then(async (res) => {
    const projects = await res.json()
    projects.forEach(project => {
        project.teammember && project.teammember.forEach(member => {
        if (userArray.indexOf(member.user) === -1) {
            userArray.push(member.user)
            fetchUserTimelogs(member.user)
            .then(async (res) => {
                const timesheet = await res.json()
                if (timesheet)
                timesheet.forEach(sheet => {
                    timeSheets.push(sheet)
                });
                const newTimesheet = this.state.timesheets.concat(timesheet);
                this.setState({timesheets: newTimesheet});
            })
        }
        })
    })
})
Alex Wiley
  • 146
  • 2
  • 6
0

I believe that the function fetchTimesheets() is acting synchronously, you can change the function definition to be async and then call the method to be await fetchTimesheets().

Sasuke Uchiha
  • 421
  • 6
  • 17