Search code examples
reactjsmomentjsstatesetstate

React new given value by set-state doesn't update component value


I'm working on a week calendar and I am trying to make It so that my calendar can show future weeks and travel back to the current week. When the button 'forward' is clicked I want to show give a new value to my state. Which works fine (It works in console) only my view doesn't change so I think it doesn't update the component with the new value. Does anyone know what I can do to make my component show the updated value?

code:

export default class Calendar extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      lastUid: 1,
      selectedIntervals: [],
      serviceDuration: 0,
      showCalendarDay:moment(),
    }
  }

  handleMoveToCurrentDay=(event)=>{
         this.setState({
           showCalendarDay:moment(),
         })
       }

  handleMoveToFutureDay=(event)=>{
    const day = this.state.showCalendarDay
    console.log('day', this.state.showCalendarDay)
    this.setState({
      showCalendarDay:day.add(7,'days'),
    })
    console.log('showCalendarDay', this.state.showCalendarDay)
}


  render() {

    return (
      <React.Fragment>

        <div id="calendar-page">
          <div id='calendar-header'>
            <div>
              <button onClick={this.handleMoveToCurrentDay}>Today</button>
              <button>previous</button>
              <button onClick={this.handleMoveToFutureDay}>forward</button>
            </div>

          </div>
          <WeekCalendar
            firstDay={this.state.showCalendarDay}
            startTime={moment({ h: 8, m: 0 })}
            endTime={moment({ h: 21, m: 0 })}
            scaleUnit={30}
            cellHeight={50}
            numberOfDays={7}
            selectedIntervals={this.state.selectedIntervals}
            modalComponent={CalenderModal}
            eventSpacing={20}
          />
        </div>
      </React.Fragment>
    )
  }
}


Solution

  • You can see in the docs for moment that add mutates the original date object.

    This means you're mutating state when you do this:

    const day = this.state.showCalendarDay
    this.setState({
      showCalendarDay:day.add(7,'days'),
    })
    

    When you mutate state, react doesn't always catch the change and doesn't have any way to know it should re-render.

    You need to first create a copy of the original moment object. A more detailed explanation is given here.

    The result will be something like this:

    const day = this.state.showCalendarDay.clone();
    this.setState({
      showCalendarDay:day.add(7,'days'),
    })