Home > Software engineering >  Why is my React component not re-rendering upon state change with Date?
Why is my React component not re-rendering upon state change with Date?

Time:12-31

I am building a React component that allows a user to click a button to move the date forward by 10 days. My code seems to update the state 'selectedDate' but the component does not re-render. I have tried swapping the state to a number (e.g 500) and having it increment by 1 each time and that does make the component re-render. For some reason, it won't re-render when a state is a Date object.

import React from 'react';
import { useState, useEffect } from 'react';

const BrowserHeader = () => {
  
  const today = new Date();
  
  const [selectedDate, setSelectedDate] = useState(today);

  const onButtonClick = () => {
    const currentDate = selectedDate;
    currentDate.setDate(currentDate.getDate() 10);
    setSelectedDate(currentDate);
    console.log('selectedDate is now:', selectedDate);
  };


  return (
    <div className='browser-header'>
      <button>
        <i className="fas fa-fast-backward"></i>
      </button>
      <form>
        <label>Date:</label>
        <input 
          value={selectedDate}
          onChange={e => setSelectedDate(e.target.value)}
        />
        <button><i className="fas fa-sync-alt"></i></button>
      </form>
      <button onClick={onButtonClick}>
        <i className="fas fa-fast-forward" ></i>
      </button>
    </div>
    );
};

export default BrowserHeader;

CodePudding user response:

Change your onClick handler like below. Instead of updating the currentDate. You need to create a new date then change it and set it as the current state. Otherwise react will ignore the rerender considering the referential equality.

  const onButtonClick = () => {
    // create a new date object using prevoius state
    const newDate = new Date(selectedDate.getDate());
    // update it
    newDate.setDate(selectedDate.getDate()   10);
    // set it as the new state
    setSelectedDate(newDate);
  };

By adding a simple value check function to your current implementation, You can see that the state has actually updated to date ahead of 10 days but rendering has not happened => https://codesandbox.io/s/elated-pond-g46mm?file=/src/App.js

NOTE: You will notice the same issue with any mutable data structures like Array, Date, Object, ...etc.

CodePudding user response:

I read this and realised where things were going wrong... How to clone a Date object?

Essentially, I was mutating state the incorrect way when I duplicated the date object.

CodePudding user response:

You create a new Date object from the existing date it'll rerender the component.

const today = new Date();
const [selectedDate, setSelectedDate] = useState(today);

const onButtonClick = () => {
  const currentDate = new Date(selectedDate); // update here
  currentDate.setDate(currentDate.getDate()   10);
  setSelectedDate(currentDate);
  console.log("selectedDate is now:", selectedDate);
};
  • Related