#reactjs #react-context
Вопрос:
У меня есть приложение react, которое должно отображаться в двух разных корневых элементах DOM. Каков наилучший способ обмена данными между ними на основе изменений внутри одного из них? Похоже, я не могу обернуть два приложения в поставщика контекста или использовать способ состояния/эффекта/обратного вызова для связи между ними.
ReactDOM.render(
<ReactApp1 componentData={}/>
, rootElement1
);
ReactDOM.render(
<ReactApp2 componentData={}/>
, rootElement2
);
Ответ №1:
Если единственная причина, по которой вы разделяете вещи, заключается в том, что вам нужно поместить контент в два несвязанных узла dom, вы можете добиться этого с помощью портала вместо двух вызовов ReactDOM.render. Таким образом, вы можете использовать стандартные реквизиты и/или контекст для передачи данных между вашими компонентами.
ReactDOM.render(
<App />
rootElement1
)
const App = () => {
const rootElement2 = /* some code to select rootElement2 from the page. eg, document.getElementById('someId') */
return (
<>
<ReactApp1 componentData={/*...*/}/>
{React.createPortal(<ReactApp2 componentData={/*...*/} />, rootElement2)}
</>
)
}
Если это невозможно, и вам нужны совершенно отдельные вызовы для ReactDOM.render, то, скорее всего, вам нужно будет создать какой-нибудь паб/суб-код и заставить приложения отправлять сообщения друг другу. Если у вас есть любимая библиотека для источников событий, вы можете использовать ее, или если вы хотите создать свою собственную, она может выглядеть примерно так:
// These lines will probably be in their own file
const subscriptions = [];
export const subscribe = (callback) => {
subscriptions.push(callback);
const unsubscribe = () => {
const i = subscriptions.findIndex(callback);
subscriptions.splice(i, 1);
}
return unsubscribe
}
export const publish = (data) => {
[...subscriptions].forEach(callback => callback(data));
}
// Used like:
const ReactApp1 = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// Listen to messages
const unsubscribe = subscribe((data) => {
setCount(data);
});
return unsubscribe;
}, []);
return <div onClick={() => {
publish(count 1);
}}/>
}
Комментарии:
1. Спасибо @nicholas-tower. Порталы, похоже, правильный путь. Дадим ему шанс.