0
votes

I am trying to pass context to an element manually rendered to the dom (because of a third-party library).

For some reason the context is not being passed correctly. I end up with:

Portal Context: false

Regular Context: true

import React, { useEffect, useContext, useRef } from "react";
import ReactDOM from "react-dom";

const AppContext = React.createContext(false);

function RenderAppContext() {
  const context = useContext(AppContext);
  return <>{JSON.stringify(context)}</>;
}

function App() {
  const portalRef = useRef(null);
  useEffect(() => {
    ReactDOM.render(
      ReactDOM.createPortal(<RenderAppContext />, portalRef.current),
      document.createElement("div")
    );
  }, []);
  return (
    <AppContext.Provider value={true}>
      <div style={{ display: "flex" }}>
        <span>Portal Context:</span>&nbsp;
        <div ref={portalRef} />
      </div>
      <div style={{ display: "flex" }}>
        <span>Regular Context:</span>&nbsp;
        <RenderAppContext />
      </div>
    </AppContext.Provider>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

https://codesandbox.io/s/dawn-surf-wt0if4?file=/src/index.js

ReactDOM.render is creating another react app, with completely separate contexts. Just ReactDOM.createPortal(<RenderAppContext />, portalRef.current) should be all that is needed for your portal. If you want to move where it is rendered to outside of the structure of your app just replace portalRef.current with the DOM element where you would like it to render (i.e. add an extra div to your body tag in your HTML give it an id of "portal" and then use document.getElementById('portal') or your preferred method of getting a reference to the element) - Jacob Smit