#reactjs
#reactjs
Вопрос:
Целью этого компонента Upsell является отображение чего-либо в определенной области (портал). Поэтому он будет принимать элемент DOM и createPortal
от этого. Проблема в том, что widgetDom всегда имеет значение null и приводит к тому, что createPortal не получил возможности для рендеринга.
В consumer я использую useRef
и передаю widgetRef.current
компонент Upsell. Я ожидаю, что при widgetRef
подключении реального элемента widgetRef.current
изменения приведут к повторному обновлению компонента, но этого не происходит.
Можете ли вы взглянуть на следующий код или песочницу? Спасибо!
const Upsell: React.FC<{ widgetDom: HTMLElement | null }> = ({ widgetDom }) => {
return (
<div className="box">
<h1>Order Summary</h1>
{widgetDom amp;amp; 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>
);
}
Ответ №1:
Ссылки по дизайну не вызывают повторной визуализации при их изменении:
Имейте в виду, что useRef не уведомляет вас об изменении его содержимого. Изменение свойства .current не приводит к повторному отображению. Если вы хотите запустить некоторый код, когда React присоединяет или отсоединяет ссылку к DOM-узлу, вы можете вместо этого использовать ссылку обратного вызова.
Самое простое решение — использовать state вместо 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>
);
}