Geoffrey Hutson
Geoffrey Hutson

Reputation: 157

Handling Checkboxes in React

I have a component that I am writing that handles the days and hours of the week.The main component that passes in a state of time to the sub component "UpdateHours" passes in the days of the week in an object, all the days are set to a default of true. So all the Check boxes are all checked by default. When I click on the day, the object is updated to false on my console but the check box remains checked even when the value is set to false. A curious part, when I click my button on the page that updates the backend the boxes I checked false become unchecked.

The object being passed through from the parent component

function handleAddNewHour() {
    var uid = generateUUID();
    var newHour = {
      mon: true,
      tue: true,
      wed: true,
      thu: true,
      fri: true,
      sat: true,
      sun: true,
      start: 0,
      end: 0,
      service_type: "all",
      id: uid
    };

    setTime(newHour);
  }



 {time != null ? (<UpdateHour time={time} setTimeChange={handleTimeUpdate}/>) : (  "" )}

The element on UpdateHours.js

 <div className="newHoursDay" onClick={() => handleDayChange("mon")}>
            <input
              type="checkbox"
              name="new_hours_mon"
              checked={props.time.mon}
              value={props.time.mon}
              onChange={() => handleDayChange("mon")}
            />
            <label>Mon</label>
          </div>

Here are the functions

  function handleDayChange(day) {
    let hourData = props.time;
    hourData[day] = !props.time[day];
    props.setTimeChange(hourData);

  }

  function handleServiceChange(serviceType) {
    props.time[serviceType] = serviceTypes;
    setState({});
  }

This function calls my function that updates the firestore database with the new object

function handleSave() {
    var hoursData = {
      hours: {}
    };
    if (typeof store.hours !== "undefined") {
      hoursData.hours = store.hours;
    }
    hoursData.hours[props.time.id] = {};
    Object.keys(props.time).forEach(prop => {
      if (prop === "id") {
        hoursData.hours[props.time.id][prop] = props.time[prop];
      }
    });
    changeStoreData(hoursData);

    //updatestore
  }

Upvotes: 0

Views: 72

Answers (1)

Eric Gibby
Eric Gibby

Reputation: 231

It looks like in your handleDayChange function, you're updating the value directly on your time prop. It's worth noting that props in React should be read-only (https://reactjs.org/docs/components-and-props.html#props-are-read-only). The reason being, React does not do a deep comparison, but is only checking whether the reference has changed.

Because props.time is an object, when you call let hourData = props.time you're setting hourData equal to the reference to props.time. When you then update values on hourData, it's actually updating props.time, and when you pass hourData to props.setTimeChange it's passing the reference to props.time. Since the reference hasn't changed, React doesn't know that the object has mutated, and therefore doesn't render again with the updated values.

Hopefully it's as simple as updating your handleDayChange function to create a new object rather than mutating props.time:

function handleDayChange(day) {
    const hourData = {
        ...props.time,
        [day]: !props.time[day]
    };
    props.setTimeChange(hourData);

}

Upvotes: 1

Related Questions