2

I am trying to give few dates to state.periods array. But it is not working. My code is as follows.

class SmallTable extends Component {
    constructor(props) {
        super(props);
        console.log(props.startDate)
        this.state = {
            turns: [],
            periods: []
        }
    }

componentDidMount() {
    //calculate years/ months and keep in one array
         const today = new Date();
         var periods1 = [];
         if (this.props.period=="year") { //if year calculate from last year last date
             const lastYearLastDate= new Date(new Date().getFullYear()-1, 11, 31)
             periods1.push(lastYearLastDate.getFullYear()+"-"+(lastYearLastDate.getMonth()+1)+"-"+lastYearLastDate.getDate());

             var lastYearFirstDate= new Date(lastYearLastDate.getFullYear()-1,0,1);

             //for the remaining periods
             for (var i=0;i<this.props.numberOfPeriods-1;i++) {
                 periods1.push(lastYearFirstDate.getFullYear()+"-"+(lastYearFirstDate.getMonth()+1)+"-"+lastYearFirstDate.getDate());
                 lastYearFirstDate = new Date(lastYearFirstDate.getFullYear()-1,0,1);
             }


         }


        else if (this.props.period=="month") {//if month calculate from last month last date
            var d=new Date(); // current date
            d.setDate(1); // going to 1st of the month
            d.setHours(-1); // going to last hour before this date even started.
            var lastMonthLastDate = d;
            periods1.push(lastMonthLastDate.getFullYear()+"-"+(lastMonthLastDate.getMonth()+1)+"-"+lastMonthLastDate.getDate());

            //go to last month  first date
            var lastMonthFirstDate = new Date(lastMonthLastDate.getFullYear(), lastMonthLastDate.getMonth(),1);

            //for the remaining periods
            for (var i=0;i<this.props.numberOfPeriods-1;i++) {
                periods1.push(lastMonthFirstDate.getFullYear()+"-"+(lastMonthFirstDate.getMonth()+1)+"-"+lastMonthFirstDate.getDate());

                lastMonthFirstDate=new Date(lastMonthFirstDate.getFullYear(), lastMonthFirstDate.getMonth()-1,1);
            }

        }

console.log(periods1); -->prints  ["2017-12-31", "2016-1-1", "2015-1-1", "2014-1-1"]
        this.setState((prevState)=>{
            return {
                periods: prevState.periods.push(periods1)
            }
        });
        console.log(this.state.periods) --> prints []

    }
render() {

        return ( <div></div>)
}

How to get values in periods1 to periods state. I am trying to insert periods1 array into state periods array. Those are strings. Pls suggest where the error might be.

  • Possible duplicate of [setState in reactjs is Async or Sync](https://stackoverflow.com/questions/36085726/setstate-in-reactjs-is-async-or-sync) – Agney Feb 22 '18 at 10:34
  • `prevState.periods.push(periods1)` does *not* return your array. You need to `push()` and *then* return – haim770 Feb 22 '18 at 10:34

5 Answers5

2

You're setting this.state.periods to the result of a push operation. But push returns the new array length, not the array itself. Try this instead:

periods: [...prevState.periods, periods1]
Miguel Calderón
  • 3,001
  • 1
  • 16
  • 18
2

You have a few issues.

For the code here:

return {
    periods: prevState.periods.push(periods1)
}

You never want to mutate state. Instead, you should create a new array object and then add the data, like so:

return {
    periods: prevState.periods.concat([periods1])
}

Secondly, your console.log is in the wrong place

console.log(this.state.periods) --> prints []

setState happens asynchronously and thus may not finish by the time your componentDidMount method returns. Instead, put that console.log inside your render function to see the new state.

AnilRedshift
  • 7,937
  • 7
  • 35
  • 59
2

push() doesn't return a value. You should use:

this.setState((prevState)=>{
    let old = prevState.periods.slice();
    old.push(periods1);
    return {
        periods: old
    }
});
Arsenio Siani
  • 261
  • 3
  • 10
2

If you expect this.state.periods to be an array of arrays ([["2017-12-31", "2016-1-1", "2015-1-1", "2014-1-1"]]) you can push your array following an immutable pattern using the spread operator :

this.setState((prevState) => ({
       periods: [...prevState.periods, periods1]
    }), () => { console.log(this.state.periods) } );

You can notice the function passed as second param of setState() is a callback to execute console.log() after the state update.

If you want to push periods1 values in this.state.periods you can do this :

this.setState((prevState) => ({
       periods: [...prevState.periods, ...periods1]
    }));
Dyo
  • 4,429
  • 1
  • 15
  • 30
1

Try to make a copy of your original state, so that you can perform setState in an immutable fashion.

const periods = [...this.state.periods];
periods.push(periods1);
this.setState({periods: periods});
izengod
  • 1,116
  • 5
  • 17
  • 41