TanStackT
TanStack2y ago
1 reply
living-lavender

Pass context to another root (createRoot)

I'm trying to create a map control using "react-map-gl" which has a tanstack router <Link/> component in it. In order to create a control on the map I have to create a new react root using React.createRoot. That react root doesn't have access to that actual app's <RouterProvider/> context so the <Link/> component doesn't work. It gives some error about state being null.

I can't wrap the new root in another <RouterProvider/> because I don't want to render an entire new app/routeTree. I just want to be able to use the <Link/> component.

I've also tried using getRouterContext() and routerContext.Provider similar to here:

https://github.com/TanStack/router/blob/main/packages/react-router/src/RouterProvider.tsx#L84

but that returns an errors that indicates that it requires a route to be matched in its children.

export interface ControlProps {
  className?: string;
  position: ControlPosition;
  children?: React.ReactNode;
}

function Control({ className, position, children }: ControlProps) {
  const context = useContext(MapContext);

  const [root, setRoot] = useState<Root | null>(null);

  useEffect(() => {
    const el = document.createElement("div");
    el.className = `maplibregl-ctrl maplibregl-ctrl-group ${className}`;
    const root = createRoot(el);
    setRoot(root);

    const { map } = context;

    const ctrl: IControl = {
      onAdd() {
        return el;
      },
      onRemove() {
        return el;
      },
    };

    map.addControl(ctrl, position);

    return () => {
      setTimeout(() => root.unmount());
      map.removeControl(ctrl);
      el.remove();
    };
  }, [context, position, className]);

  const routerContext = getRouterContext();
  const router = useRouter();

  useEffect(() => {
    if (root) {
      // Need to wrap this children node with the app's router context
      root.render(children);
    }
  }, [root, children, routerContext, router]);

  return null;
}
GitHub
🤖 Fully typesafe Router for React (and friends) w/ built-in caching, 1st class search-param APIs, client-side cache integration and isomorphic rendering. - TanStack/router
router/packages/react-router/src/RouterProvider.tsx at main · TanSt...
Was this page helpful?