NextJS 16, use child component in a parent component #204025
Replies: 4 comments 1 reply
|
You're right — just importing it won't let the parent control the modal. The modal state lives inside the child. The parent can't reach in and flip it open unless you expose a way to do that. 1. Lift state up (simplest) // Parent
const [showModal, setShowModal] = useState(false);
return (
<>
<button onClick={() => setShowModal(true)}>Open from parent</button>
<CounterModal isOpen={showModal} onClose={() => setShowModal(false)} />
</>
);
// Child (CounterModal)
export default function CounterModal({ isOpen, onClose }) {
// use isOpen / onClose instead of internal state
}
2. Forward a ref with useImperativeHandle (if you must keep state in child)
const Child = forwardRef((props, ref) => {
const [isOpen, setIsOpen] = useState(false);
useImperativeHandle(ref, () => ({
open: () => setIsOpen(true),
close: () => setIsOpen(false),
}));
// ...
});
// Parent
const childRef = useRef(null);
<button onClick={() => childRef.current?.open()}>Open</button>
<Child ref={childRef} />
Use sparingly — it breaks the "data flows down" mental model.
3. Controlled + uncontrolled hybrid (flexible)
Let the child manage its own state unless the parent passes isOpen — then it becomes controlled.
// Child
export default function CounterModal({ isOpen, onClose, defaultOpen = false }) {
const [internalOpen, setInternalOpen] = useState(defaultOpen);
const open = isOpen ?? internalOpen;
const setOpen = isOpen ? onClose : setInternalOpen; // simplified
// ...
}
Which to pick:
- Parent owns the trigger → lift state (#1)
- Child is a reusable library component → hybrid (#3)
- Weird legacy constraint → ref (#2)
Don't overthink it. Most of the time, lifting state is the cleanest. The child becomes dumber (just UI), the parent
decides when it shows. |
|
It depends on how your modal is implemented. If the modal state ( From my experience, the cleanest approach is to lift the modal state up to the parent. Keep If you can share a small code snippet of your parent and child components, it'll be much easier to suggest the best approach. |
|
It depends on where you want the modal's state to live. If the modal is only used within the child component, then importing the child into the parent is enough—the child can continue managing its own However, if the parent needs to control when the modal opens (or multiple components need to interact with it), you should "lift the state up" to the parent. The parent owns the modal state and passes it to the child via props. For example: function Parent() {
const [isOpen, setIsOpen] = useState(false);
return (
<Child
isOpen={isOpen}
onOpen={() => setIsOpen(true)}
onClose={() => setIsOpen(false)}
/>
);
}
function Child({ isOpen, onOpen, onClose }) {
return (
<>
<button onClick={onOpen}>Open Modal</button>
{isOpen && <Modal onClose={onClose} />}
</>
);
}If the parent only needs to render the child, then no changes are necessary. If the parent needs to control the modal, lifting the state up is the idiomatic React approach. Could you share:
|
|
Importing the child component is enough if the parent only needs to display it and the modal is still opened from the button inside the child. However, if a button in the parent should open the modal inside the child, the parent needs some way to control it. Since you are using the Tailwind command API, the parent button can target the dialog rendered by the child. The important part is that function ParentComponent() {
return (
<>
<button
type="button"
command="show-modal"
commandFor="counter-dialog"
>
Open modal
</button>
<ChildComponent />
</>
);
}function ChildComponent() {
return (
<el-dialog>
<dialog id="counter-dialog">
<p>Modal content</p>
<button
type="button"
command="close"
commandFor="counter-dialog"
>
Close
</button>
</dialog>
</el-dialog>
);
}So you do not need to copy the child component code into the parent. Keep the modal in the child and let the parent button reference its dialog ID. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
🏷️ Discussion Type
Question
Body
I have a child component (a simple counter) with a button and a modal. When clicking the button the modal opens. This works only in the child component. Now I need to add this functionality in a parent component. Just importing this component into the parent will not be enough I think?
Guidelines
All reactions