Reputation: 6755
The intention of this Upsell component is to render something in certain area (portal). So it will accept a DOM element, and createPortal
on that. The problem is the widgetDom is always null and cause the createPortal didn't get chance to render.
In consumer I use useRef
and pass the widgetRef.current
to the Upsell component. I am expecting when the widgetRef
attached the real element, widgetRef.current
changes will cause the Upsell component rerender, but it is not happening.
Can you have a look the following code or the sandbox? Thank you!
const Upsell: React.FC<{ widgetDom: HTMLElement | null }> = ({ widgetDom }) => {
return (
<div className="box">
<h1>Order Summary</h1>
{widgetDom && createPortal(<h2>Order Summary Widget</h2>, widgetDom)}
</div>
);
};
export default function App() {
const widgetDom = React.useRef<HTMLElement | null>(null);
return (
<div className="App">
<div className="box" style={{ width: "60%" }}>
<div className="box">
<h1>Ad Selection</h1>
</div>
<Upsell widgetDom={widgetDom.current} />
</div>
<div className="box" style={{ width: "40%" }}>
<div id="orderSummaryWidget" ref={widgetDom} className="box"></div>
</div>
</div>
);
}
Upvotes: 2
Views: 3390
Reputation: 6637
Refs by design don't cause a re-render when they change:
Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.
The easiest fix is to use state instead of a ref:
export default function App() {
const [widgetDom, setWidgetDom] = useState<HTMLElement | null>(null);
return (
<div className="App">
<div className="box" style={{ width: "60%" }}>
<div className="box">
<h1>Ad Selection</h1>
</div>
<Upsell widgetDom={widgetDom} />
</div>
<div className="box" style={{ width: "40%" }}>
<div id="orderSummaryWidget" ref={setWidgetDom} className="box"></div>
</div>
</div>
);
}
Upvotes: 3