-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Revisit Controlled and UnControlled Component #110
Labels
Comments
Take Dialog component as an exampleimport React, { useState, useEffect } from 'react';
interface DialogProps {
// For controlled usage
open?: boolean;
onOpenChange?: (open: boolean) => void;
// For uncontrolled usage
defaultOpen?: boolean;
children?: React.ReactNode;
}
const Dialog = ({
open: controlledOpen,
defaultOpen = false,
onOpenChange,
children
}: DialogProps) => {
// Internal state for uncontrolled mode
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
// Determine if we're in controlled or uncontrolled mode
const isControlled = controlledOpen !== undefined;
// Use controlled value if provided, otherwise use internal state
const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
// Handler for both controlled and uncontrolled modes
const handleOpenChange = (newOpen: boolean) => {
// In uncontrolled mode, update internal state
if (!isControlled) {
setUncontrolledOpen(newOpen);
}
// Always call onOpenChange if provided
onOpenChange?.(newOpen);
};
// Update internal state if controlled prop changes
useEffect(() => {
if (isControlled) {
setUncontrolledOpen(controlledOpen);
}
}, [isControlled, controlledOpen]);
return (
<>
{/* Example implementation of dialog - simplified for clarity */}
{isOpen && (
<div className="fixed inset-0 bg-black/50">
<div className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white p-6 rounded-lg">
{/* Close button */}
<button
onClick={() => handleOpenChange(false)}
className="absolute top-2 right-2"
>
×
</button>
{/* Dialog content */}
{children}
</div>
</div>
)}
</>
);
};
// DialogTrigger component to handle opening
interface DialogTriggerProps {
asChild?: boolean;
children: React.ReactNode;
}
const DialogTrigger = ({ asChild, children }: DialogTriggerProps) => {
return (
<button onClick={() => {
// Find closest Dialog component and update its state
// In real implementation, this would use React Context
// to communicate with parent Dialog
}}>
{children}
</button>
);
};
// Example usage:
const Example = () => {
// Uncontrolled usage
return (
<Dialog defaultOpen={false}>
<DialogTrigger>Open Dialog</DialogTrigger>
</Dialog>
);
// Controlled usage
const [open, setOpen] = useState(false);
return (
<Dialog
open={open}
onOpenChange={setOpen}
>
<DialogTrigger>Open Dialog</DialogTrigger>
</Dialog>
);
}; |
Understand controlled vs uncontrolledfunction UncontrolledInput() {
const inputRef = useRef();
const handleSubmit = () => {
console.log(inputRef.current.value);
};
return (
<input
ref={inputRef}
defaultValue="initial value"
/>
);
} function ControlledInput() {
const [value, setValue] = useState('');
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Controlled vs Uncontrolled component
Understand it from two levels:
The text was updated successfully, but these errors were encountered: