SolidJSS
SolidJSโ€ข2y agoโ€ข
5 replies
Liquido

How to store JSX element in a signal and render it from other elements

I have created a dialog system using context where the dialog that I want to render is stored via a function provided by context and the provider is the one that renders the dialog:

import { render, Portal } from "solid-js/web";
import { createContext, useContext, createSignal, type JSX, type Accessor } from "solid-js";

export type DialogContextValue = {
  openDialog(element: JSX.Element): void;

  closeDialog(): void;
};

export const DialogContext = createContext<DialogContextValue>({
  openDialog() {},
  closeDialog() {},
});

type DialogProviderProps = {
  children: JSX.Element
}

export function DialogProvider(props: DialogProviderProps) {
  const [activeDialog, setActiveDialog] = createSignal<JSX.Element | undefined>(undefined)

  const openDialog = (element: JSX.Element) => {
    setActiveDialog(element)
  }

  const closeDialog = () => {
    setActiveDialog(undefined);
  }

  return (
    <DialogContext.Provider value={{ openDialog, closeDialog }}>
      {props.children}
      {activeDialog && <Portal>{activeDialog()}</Portal>}
    </DialogContext.Provider>
  );
}

function useDialog() { return useContext(DialogContext); }

function App() {
  const dialog = useDialog();
  return <button onClick={() => {
    dialog.openDialog(<button onClick={dialog.closeDialog}>Dialog open. Click to close</button>);
  }}>Open dialog</button>
}


Playground Link: https://playground.solidjs.com/anonymous/5d842f3f-3a3c-49b8-8287-9d46e0d29ca1

This works well but I have two problems. Firstly, I get a warning in the console when I trigger the modal:

dev.js:836 computations created outside a createRoot or render will never be disposed

And secondly, some components are not rendered when I open the modal. For example, I installed solid-icons package to render an icon. The icon is not rendered on first open but when I modify the code to trigger hot reload, the icon component is rendered inside it. The icons are rendered fine everywhere else.
Was this page helpful?