Hint
Controlled = React state is truth. Uncontrolled = DOM is truth. Controlled components are preferred because you can validate, transform, and react to every change.
// Controlled: parent owns value, child just displays
function ControlledInput(value, onChange) {
// The value comes from outside — child can't change it directly
return {
value,
type: 'controlled',
handleChange(newVal) {
onChange(newVal); // notify parent — parent decides if value changes
}
};
}
// Uncontrolled: component owns value internally
function UncontrolledInput(defaultValue) {
let internalValue = defaultValue;
return {
value: internalValue,
type: 'uncontrolled',
handleChange(newVal) {
internalValue = newVal; // self-managed, no parent needed
}
};
}
let parentValue = 'hello';
const controlled = ControlledInput(parentValue, v => { parentValue = v; });
const uncontrolled = UncontrolledInput('world');
controlled.handleChange('new');
uncontrolled.handleChange('updated');
console.log(parentValue);
console.log(uncontrolled.value);
console.log(controlled.type);new world controlled
Explanation: Controlled: onChange updates parentValue, which would flow back as the new value prop. Uncontrolled: internalValue updates but the value property captured the initial 'world'.
Key Insight: Controlled = React state is truth. Uncontrolled = DOM is truth. Controlled components are preferred because you can validate, transform, and react to every change.