Reputation: 10144
A checkbox such as the one below triggers the dreaded "Input elements must be either controlled or uncontrolled" warning
const Checkbox = props =>
<label className="checkbox">
<input type="checkbox" checked={props.checked} defaultChecked={false}/>
</label>
All examples of uncontrolled components use the classed based approach for defining components, and I have found none that used functional component.
Is it possible at all to define an uncontrolled component defined with a function ?
Upvotes: 0
Views: 816
Reputation: 1720
Here is my second approach: https://codesandbox.io/s/fervent-glitter-7nxy5?file=/src/App.js:0-1090
I don't think this is how I would design a component, but it is basically what you are asking for. A component that doesn't use the onChange-binding but instead uses useRef
and updates the checkbox that way.
export default function App() {
const [checked, setChecked] = useState(false);
const [checked2, setChecked2] = useState(true);
return (
<div className="App">
<h2>Usecase #1</h2>
<div>currently: {checked ? "true" : "false"}</div>
<button onClick={e => setChecked(!checked)}>toggle</button>
<Checkbox checked={checked} setChecked={setChecked} />
<hr />
<h2>Usecase #2</h2>
<div>currently: {checked2 ? "true" : "false"}</div>
<button onClick={e => setChecked2(!checked2)}>toggle</button>
<Checkbox checked={checked2} setChecked={setChecked2} />
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const Checkbox = ({ checked, setChecked }) => {
const checkboxRef = useRef(null);
useEffect(() => {
// Update from props
checkboxRef.current.checked = checked;
const handleChange = event => setChecked(event.target.checked);
// Update parent from change event
checkboxRef.current.addEventListener("change", handleChange);
// Cleanup
return checkboxRef.current.removeEventListener("change", handleChange);
}, [checked, setChecked]);
return (
<label className="checkbox">
<input type="checkbox" ref={checkboxRef} />
</label>
);
};
Upvotes: 1
Reputation: 3274
Remove the checked
and it will become uncontrolled:
const Checkbox = props =>
<label className="checkbox">
<input type="checkbox" defaultChecked={false}/>
</label>
When you add checked
, React also expects onChange
. It's either both for controlled, or none for uncontrolled
Upvotes: 0
Reputation: 1720
You can just have an empty onChange:
const Checkbox = props => (
<label className="checkbox">
<input type="checkbox" checked={props.checked} onChange={() => void 0} />
</label>
);
Upvotes: 0