IM GONNA LOSE MY MIND, ITS BEEN 5 HOURS, PLEASE TELL ME WHAT IS GOING ON.
in my parent I have
const [showColorbar, setShowColorbar] = useState(
colorbarService.isColorbarToggled(viewportId),
);
I pass this value to
<SwitchButton
label="Display Color bar"
checked={showColorbar}
onChange={() => {
onSetColorbar({
viewportId,
options: {
colormaps,
ticks: {
position: colorbarTickPosition,
},
width: colorbarWidth,
position: colorbarContainerPosition,
activeColormapName: colorbarInitialColormap,
},
});
}}
/>;
and this is switchbutton
import React, { useCallback, useState } from "react";
import "./switchButton.css";
export enum SwitchLabelLocation {
left,
right,
}
export type SwitchButtonProps = {
checked?: boolean;
label?: string;
labelLocation?: SwitchLabelLocation;
onChange?: (checked: boolean) => void;
};
const SwitchButton = ({
label,
checked = false,
onChange,
labelLocation = SwitchLabelLocation.left,
}: SwitchButtonProps) => {
const [isInputChecked, setIsInputChecked] = useState(checked);
const onHandleChange = useCallback(
(event) => {
setIsInputChecked(event.target.checked);
onChange?.(event.target.checked);
},
[onChange],
);
// Thanks goes to https://codepen.io/lhermann/pen/EBGZRZ for the inspiration to the code below.
return (
<label className="switch-button flex w-full cursor-pointer items-center justify-between text-[14px]">
{label && labelLocation === SwitchLabelLocation.left && (
<div>{label}</div>
)}
<div className="relative">
<input
className="absolute hidden"
type="checkbox"
onChange={onHandleChange}
checked={isInputChecked}
/>
<div className="switch-button-outer border-common-bright bg-primary-dark block h-[16px] w-[30px] rounded-full border"></div>
<div className="switch-button-dot bg-common-bright absolute left-[4px] top-[3px] h-[10px] w-[10px] rounded-full transition duration-150 ease-in-out"></div>
</div>
{label && labelLocation === SwitchLabelLocation.right && (
<div>{label}</div>
)}
</label>
);
};
export default SwitchButton;
For some reason, SwitchButton does not CARE what the value of checked when it updates, lets say I toggle the switch on, and close the menu, the next time I opened the menu, even tho the checked prop being passed is true, it somehow says false, i dont get this.
I tried debugging for hours, Im expecting the child to update based on the parent, if the value for checked in the parent is true, when I opened and close the menu, the toggle should be on, not off.
2
Answers
It looks like the SwitchButton only uses the ‘checked’ prop to initialize ‘isInputChecked’ and then operates on ‘isInputChecked’ only. After initializaton, ‘isInputChecked’ is never updated to stay in sync with ‘checked’.
Fix it with useEffect within SwitchButton:
useEffect(()=> setIsInputChecked(checked), [checked]);
Or make SwitchButton into a controlled component by operating on ‘checked’ instead of ‘isInputChecked’ in the first place (which would be my preferred solution)
It is a bad idea to initialize your state with a prop.
Check out this.
as for the solution, you can have this inside your switch. To keep your synch