Home > Software engineering >  Adding objects to state in a for loop is only adding the last object to state
Adding objects to state in a for loop is only adding the last object to state

Time:12-22

I have an array which holds 40 objects I am looping through them with a forEach loop. Then I check if the current date is equal to the date in the objects, if it is I want to get those objects that are equal and add them to state.

I currently have it looping and the check to see if the dates match is working. Inside the if statement I just check if the dates match and if so I update state with forcast which should add the objects I want to state. But it is only adding the last one that is true to state and clearing the ones before, how can I get it to add all the objects that dates match to state.

  const [todayForcast, setTodayForcast] = useState()
  function checkDates() {
    const forcastArray = props.forcast.list // Get array containing all forcasts
    const date = new Date(); // Get current date
    const date1 = date.getDate(); // Get just todays date
    // Loop over the array and get each item
    forcastArray.forEach(forcast => {
      let get_current_dt = forcast.dt_txt // Get d & t from the obj
      let split_dt = get_current_dt.split(" ") // Split d & t at the space
      let get_full_date = split_dt[0] // Get just the date
      let get_date = get_full_date.slice(8) // Remove year & month and get just day
      if( get_date ==  date1){
        setTodayForcast(forcast)
      }
    })
  }

CodePudding user response:

What you are doing currently is each time setting the current forcast to the state (should be forecast maybe it's a typo but doesn't matter). When you set forcast you override the last one that was there, if you want to save all of them then you can do something like that.

// chose an array, maybe you want an object instead at the beginning
const [todayForcast, setTodayForcast] = useState([])
function checkDates() {
  const forcastArray = props.forcast.list // Get array containing all forcasts
  const date = new Date(); // Get current date
  const date1 = date.getDate(); // Get just todays date
  // Loop over the array and get each item
  forcastArray.forEach(forcast => {
    let get_current_dt = forcast.dt_txt // Get d & t from the obj
    let split_dt = get_current_dt.split(" ") // Split d & t at the space
    let get_full_date = split_dt[0] // Get just the date
    let get_date = get_full_date.slice(8) // Remove year & month and get just day
    if( get_date ==  date1){
      // make a new array (or object) and add the new forcast to it
      let newForecasts = [...todayForcast, forcast];
      setTodayForcast(newForecasts);
    }
  })
}

We make a new array called newForecasts and use the spread ... operator to spread whatever is inside todayForcast already and then we add the current forcast to it also giving us a new array with the addition of the current forcast. Then we set it back to todayForcast state.

CodePudding user response:

You have to use a dummy array to push in it , After the iteration you can set the dummy array into the state variable .Hope you got ....

CodePudding user response:

As Ben mentioned, you are overwriting the state each loop. Thus, at the end of the final forEach iteration, your state is the state of the last forecast. Unfortunately, the amended solution provided was not quite right. I would have commented, but my reputation is not high enough, so I'm adding a new answer.

We need to initialize an array outside of the loop. Otherwise, it will be overwritten each iteration and then we're back at square one. For example:

  const [todayForcast, setTodayForcast] = useState()
  function checkDates() {
    const forcastArray = props.forcast.list // Get array containing all forcasts
    const date = new Date(); // Get current date
    const date1 = date.getDate(); // Get just todays date
    
    // We need to initialize the array outside of the loop, otherwise it gets overwritten
    // each iteration and we're back at square one.
    const newForecasts = []; 

    // Loop over the array and get each item
    forcastArray.forEach(forcast => {
      let get_current_dt = forcast.dt_txt // Get d & t from the obj
      let split_dt = get_current_dt.split(" ") // Split d & t at the space
      let get_full_date = split_dt[0] // Get just the date
      let get_date = get_full_date.slice(8) // Remove year & month and get just day
      if( get_date ==  date1){

        // Append the current forcast to the newForescasts array defined earlier
        newForecasts.push(forcast);
      }
    })

    // After the loop is finished, set the state to the newForecasts
    setTodayForcast(newForecasts)
  }

As an aside, I'm not entirely sure what format your forcast.dt_txt is in, but you can likely simplify the rest of your code:

  const [todayForcast, setTodayForcast] = useState()
  function checkDates({ forcast }) {
    const forcastArray = forcast.list
    const date = new Date().getDate()
 
    const newForecasts = []

    forcastArray.forEach(f => {if (date == new Date(f.dt_txt).getDate()) newForecasts.push(f))}
    setTodayForcast(newForecasts)
  }

  • Related