Reputation: 88
I'm using react-hook-form V7.14.2 and I'm using a Material-UI checkbox that can be checked by the user manually or will be automatically checked depending on the values of certain inputs. This is working OK.
The issue is that when submitting the form, if the check box was checked via logic, depending on the values of certain input, the value sent to the back end will be false. If the user manually checks the check box, then it will send the correct value. -True if checked-.
I read the documentation to migrate from V6 to V7 in react-hook-form page, as I was previously using V6 and the code works there. https://react-hook-form.com/migrate-v6-to-v7/
I also read some previous answers in Stackoverflow such as this one: material-ui checkbox with react-hook-form but with no success.
Here is my code:
import React, { useContext, useState, useEffect } from "react";
import Checkbox from "@material-ui/core/Checkbox";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import { Controller, set } from "react-hook-form";
import { makeStyles } from "@material-ui/core/styles";
import { DarkThemeContext } from "../../context/DarkThemeContext";
import { useStylesSelectPropDetails } from "../../styledComponent/SelectPropDetailsStyled";
import { IMAGES_LINK } from "../../api/doFetch";
const useStylesLabel = makeStyles((theme) => ({
label: {
fontSize: "1em",
fontFamily: "Open Sans Hebrew, sans-serif !important",
fontWeight: 400,
lineHeight: 1.5,
},
}));
const CheckboxPropDetails = ({
register,
name,
label,
checked,
isShelter,
isElevator,
}) => {
const classesLabel = useStylesLabel();
const [isDarkTheme] = useContext(DarkThemeContext);
const [isChecked, setIsChecked] = useState(false);
const props = { isDarkTheme: isDarkTheme };
const classes = useStylesSelectPropDetails(props);
const handleChange = (event) => {
setIsChecked(event.target.checked);
};
useEffect(() => {
if (name === "shelter") {
if ( isShelter,) {
setIsChecked(true);
} else setIsChecked(false);
}
if (name === "elevator") {
console.log("elevator");
if (isElevator) {
console.log("isElevator", isElevator);
setIsChecked(true);
} else setIsChecked(false);
}
}, [ isShelter, isElevator]);
return (
<>
<FormControlLabel
classes={classesLabel}
control={
<Checkbox
name={name}
id={name}
defaultChecked={checked ? checked : false}
{...register(name)}
color="primary"
size={"medium"}
icon={
<img
src={`${IMAGES_LINK}/dashboard/elements/rec.svg`}
alt="Circle"
style={{ width: 20, height: 20 }}
/>
}
disableRipple
checkedIcon={
<FontAwesomeIcon
icon={faCheckCircle}
style={{ width: 20, height: 20 }}
/>
}
checked={isChecked}
onChange={(e) => handleChange(e)}
/>
}
labelPlacement="end"
label={<p className={classes.paragraphAddProp}>{label}</p>}
/>
</>
);
};
Code used with V6 on react-hook-form:
import React, { useContext, useState, useEffect } from "react";
import Checkbox from "@material-ui/core/Checkbox";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import { Controller } from "react-hook-form";
import { makeStyles } from "@material-ui/core/styles";
import { DarkThemeContext } from "../../context/DarkThemeContext";
import { useStylesSelectPropDetails } from "../../styledComponent/SelectPropDetailsStyled";
import { IMAGES_LINK } from "../../api/doFetch";
const useStylesLabel = makeStyles((theme) => ({
label: {
fontSize: "1em",
fontFamily: "Open Sans Hebrew, sans-serif !important",
fontWeight: 400,
lineHeight: 1.5,
},
}));
const CheckboxPropDetails = ({
register,
name,
label,
checked,
isShelter,
isElevator,
}) => {
const classesLabel = useStylesLabel();
const [isDarkTheme] = useContext(DarkThemeContext);
const props = { isDarkTheme: isDarkTheme };
const classes = useStylesSelectPropDetails(props);
const [isChecked, setIsChecked] = useState(false);
const handleChange = (event) => {
console.log("event", event.target.checked);
setIsChecked(event.target.checked);
};
useEffect(() => {
if (name === "shelter") {
if (isShelter) {
setIsChecked(true);
} else setIsChecked(false);
}
if (name === "elevator") {
if (isElevator) {
setIsChecked(true);
} else setIsChecked(false);
}
}, [isShelter, isElevator]);
return (
<>
<FormControlLabel
classes={classesLabel}
control={
<Checkbox
name={name}
defaultChecked={checked ? checked : false}
inputRef={register}
color="primary"
size={"medium"}
icon={
<img
src={`${IMAGES_LINK}/dashboard/elements/rec.svg`}
alt="Circle"
style={{ width: 20, height: 20 }}
/>
}
disableRipple
checkedIcon={
<FontAwesomeIcon
icon={faCheckCircle}
style={{ width: 20, height: 20 }}
/>
}
checked={isChecked}
onChange={(e) => handleChange(e)}
/>
}
labelPlacement="end"
label={<p className={classes.paragraphAddProp}>{label}</p>}
/>
</>
);
};
Control, register, and so are being pass as props from another component.
As mention before, it's working on V6. The difference in V6 and V7 is one line:
in V6
inputRef={register}
in V7
{...register(name)}
How could I make it so that when the checked value is change via logic that it will register and on submit will be send to the backend as true?
Upvotes: 3
Views: 5996
Reputation: 6949
The MUI <Checkbox />
component has a slighty different interface for setting a value
. The RHF value has to be set with checked
prop.
In v6 you just passed register
to the inputRef
, but since v7 calling register
will return an object - two properties of this object are value
and onChange
. So when spreading your register
call to the MUI <Checkbox />
you're setting the link for the actual value to the value
prop instead of using the checked
prop.
You should therefore use RHF's <Controller />
component, check the docs here for more infos about integrating external controlled components.
<FormControlLabel
control={
<Controller
name="checkbox"
control={control}
defaultValue={false}
render={({ field: { value, ref, ...field } }) => (
<Checkbox
{...field}
inputRef={ref}
checked={!!value}
color="primary"
size={"medium"}
disableRipple
/>
)}
/>
}
label="Checkbox"
labelPlacement="end"
/>
One important note: you have to set the value with checked={!!value}
to avoid a warning about changing a component from uncontrolled to controlled in case that your defaultValue
for someCheckbox
is initially undefined
.
Upvotes: 11