Charles L.
Charles L.

Reputation: 1960

ReactJS and Material UI CheckBox State Change

Im using Material UI Checkbox to create a form that takes input and then in theory adds the new values or updates the values into a state object. This form is used for both editing a holiday or creating a new holiday.

I'm struggling with finding why my state isnt being updated upon clicking on a checkbox or typing in an input box. The checkbox wont change to checked/unchecked and the input wont remvoe the value when i use backspace to remove characters or enter new characters.

Dialog Box: DialogBox

HolidayData:

{
  "id": 1,
  "ID": 1,
  "HolidayName": "New Year's Day",
  "HolidayDate": "05/20/2020",
  "Branch": null,
  "Hours": null,
  "Web": true,
  "Phone": true,
  "CoOp": false,
  "Active": true,
  "Submitted": null,
  "SubmittedBy": null,
  "Published": "05/20/2020",
  "PublishedBy": "John.Doe"
}

DialogBox Code:

const HolidayDialog = (props) => {

    const [noticeModal, setNoticeModal] = React.useState(false);
    const [selectedDate, setSelectedDate] = React.useState(new Date());
    const [holidayData, setHolidayData] = React.useState(props.data);


    useEffect(() => {
        setHolidayData(props.data);
        setNoticeModal(props.open)
    });

    const handleDateChange = (date) => {
        setSelectedDate(date);
    };

    const handleClose = () => {
        setNoticeModal(false);
    };



    const handleChange = (e) => {
      const { name, checked } = e.target;
      setHolidayData((prevState) => ({ ...prevState, [name]: checked }));
    };

   const updateValues = (e) => {
      const { name, value } = e.target;
      setHolidayData((prevState) => ({ ...prevState, [name]: value }));
   };
    return (
        <Dialog
            open={noticeModal}
            TransitionComponent={Transition}
            keepMounted
            onClose={handleClose}
            aria-labelledby="notice-modal-slide-title"
            aria-describedby="notice-modal-slide-description"
        >
            <DialogTitle id="customized-dialog-title" onClose={handleClose}>
                {holidayData.HolidayName ? holidayData.HolidayName : 'Create New Holiday'}
            </DialogTitle>
            <DialogContent dividers>
                <form noValidate autoComplete="off">
                    <div className="row">
                        <div className="col">
                            <TextField required name="HolidayName" id="outlined-basic" label="Holiday Name" variant="outlined" onChange={updateValues} value={holidayData.HolidayName ? holidayData.HolidayName : ''}/>
                        </div>
                        <div className="col">
                            <TextField id="outlined-basic" label="Branch" variant="outlined" onChange={updateValues} value={holidayData.Branch ? holidayData.Branch : 'ALL'}/>
                        </div>
                    </div>
                    <div className="row mt-3">
                        <div className="col">
                        <MuiPickersUtilsProvider utils={DateFnsUtils}>
                            <KeyboardDatePicker
                                disableToolbar
                                variant="inline"
                                format="MM/dd/yyyy"
                                margin="normal"
                                id="date-picker-inline"
                                label="Date picker inline"
                                value={selectedDate}
                                onChange={handleDateChange}
                                KeyboardButtonProps={{
                                    'aria-label': 'change date',
                                }}
                            />
                        </MuiPickersUtilsProvider>
                        </div>
                        <div className="col">
                            <TextField id="outlined-basic" label="Hours" variant="outlined" onChange={updateValues} value={holidayData.Hours ? holidayData.Hours : 'Closed'}/>
                        </div>
                    </div>
                    <div className="row mt-3">
                        <div className="col d-flex flex-column">
                            <FormControlLabel
                                control={
                                <Checkbox
                                    checked={holidayData.Web ? holidayData.Web : false}
                                    onChange={handleChange}
                                    name="Web"
                                    color="primary"
                                />
                                }
                                label="Show on Web?"
                            />
                            <FormControlLabel
                                control={
                                <Checkbox
                                    checked={holidayData.CoOp ? holidayData.CoOp : false}
                                    onChange={handleChange}
                                    name="CoOp"
                                    color="primary"
                                />
                                }
                                label="CoOp Holiday?"
                            />
                        </div>
                        <div className="col d-flex flex-column">
                            <FormControlLabel
                                control={
                                <Checkbox
                                    checked={holidayData.Phone ? holidayData.Phone : false}
                                    onChange={handleChange}
                                    name="Phone"
                                    color="primary"
                                />
                                }
                                label="Use in IVR?"
                            />
                            <FormControlLabel
                                control={
                                <Checkbox
                                    checked={holidayData.Active ? holidayData.Active : false}
                                    onChange={handleChange}
                                    disabled 
                                    name="active"
                                    color="primary"
                                />
                                }
                                label="Active"
                            />
                        </div>
                    </div>
                </form>
            </DialogContent>
            <DialogActions>
                <Button autoFocus onClick={handleClose} color="default">
                    Cancel
                </Button>
                <Button autoFocus onClick={handleClose} color="primary">
                    Create Holiday
                </Button>
            </DialogActions>
        </Dialog>
    )
}

When i check a box or try to edit an input the handleChange and updateValues are firing. I believe it may be a syntax issue, but i cant seem to find anything. When console.log'ing event.target.name i get the correct name: Web for example

EDIT: The issue appears to be with the value and checked being equal to {holidayData.Phone ? holidayData.Phone : false} or the sorts. However if i bring the values down to {holidayData.Phone} itll start to throw errors:

A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa).

It'll now allow me to check a checkbox but only once and throws this error over and over again and im not sure why or how to correct this?

Upvotes: 0

Views: 3248

Answers (1)

Pablo CG
Pablo CG

Reputation: 816

Most probably the useEffect is causing the issue. You're resetting the data each time the component gets updated. You don't need that if you're already doing that with useState.

Check my example here with only the textbox: https://codesandbox.io/s/fancy-shape-14r63?file=/src/App.js

If you uncomment the useEffect, it stops working.

Upvotes: 2

Related Questions