Skip to content

Commit

Permalink
fix(react-context): expose clients (#241)
Browse files Browse the repository at this point in the history
* fix(context): expose clients

* typo
  • Loading branch information
danilowoz authored Dec 9, 2021
1 parent a1461a0 commit f47295d
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions sandpack-react/src/contexts/sandpackContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,7 @@ class SandpackProvider extends React.PureComponent<
status: sandpackStatus,
editorState,
initMode,
clients: this.clients,
closeFile: this.closeFile,
deleteFile: this.deleteFile,
dispatch: this.dispatchMessage,
Expand Down
51 changes: 51 additions & 0 deletions sandpack-react/src/presets/CustomSandpack.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,54 @@ export const ResetButton: React.FC = () => (
</SandpackProvider>
</>
);

const ListenerIframeMessage = () => {
const [message, setMessage] = useState("Hello World");
const { sandpack } = useSandpack();

const sender = () => {
Object.values(sandpack.clients).forEach((client) => {
client.iframe.contentWindow.postMessage(message, "*");
});
};

return (
<>
<button onClick={sender}>Send message</button>
<input
onChange={({ target }) => setMessage(target.value)}
value={message}
/>
</>
);
};

export const IframeMessage: React.FC = () => (
<SandpackProvider
template="react"
customSetup={{
files: {
"/App.js": `import {useState, useEffect} from "react";
export default function App() {
const [message, setMessage] = useState("")
useEffect(() => {
window.addEventListener("message", (event) => {
setMessage(event.data);
});
}, [])
return <h1>{message}</h1>
}
`,
},
}}
>
<ListenerIframeMessage />
<SandpackLayout>
<SandpackCodeEditor />
<SandpackPreview />
</SandpackLayout>
</SandpackProvider>
);
2 changes: 2 additions & 0 deletions sandpack-react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
ListenerFunction,
SandpackBundlerFiles,
SandpackError,
SandpackClient,
SandpackMessage,
UnsubscribeFunction,
} from "@codesandbox/sandpack-client";
Expand Down Expand Up @@ -34,6 +35,7 @@ export interface SandpackState {
environment?: SandboxEnvironment;
status: SandpackStatus;
initMode: SandpackInitMode;
clients: Record<string, SandpackClient>;

runSandpack: () => void;
registerBundler: (iframe: HTMLIFrameElement, clientId: string) => void;
Expand Down
20 changes: 20 additions & 0 deletions website/docs/docs/advanced-usage/provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,26 @@ the scenes and the template, if omitted, is `vanilla`.
However, you will notice that the buttons on the Preview look off. This is
because there is no styling applied to the sandpack components. For styling and theming, you need the `SandpackThemeProvider`.

### Clients

Under one Sandpack provider, you can have multiple `sandpack-clients`. For example, the most common case for multiple clients is when more than one SandpackPreview has been rendered.

To access all the clients or to pass messages to the iframes under the same provider, use the [`useSandpack`](/api/react/#usesandpack) hook, which gives a way to interact with these clients:

```js
const ListenerIframeMessage = () => {
const { sandpack } = useSandpack();

const sender = () => {
Object.values(sandpack.clients).forEach((client) => {
client.iframe.contentWindow.postMessage("Hello World", "*");
});
};

return <button onClick={sender}>Send message</button>;
};
```

## Theme Provider

The `SandpackThemeProvider` is also exported from the main package. It needs to render inside the `SandpackProvider` and it needs to surround any component that requires styling from sandpack.
Expand Down

0 comments on commit f47295d

Please sign in to comment.