From 55e8947ed10d06f0313d67cd755b335b7029d189 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 10:30:09 +0000 Subject: [PATCH 01/26] Update ci.json and useClient.ts --- .codesandbox/ci.json | 2 +- sandpack-react/src/contexts/utils/useClient.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index 8678701e7..fabf52bc2 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,5 +1,5 @@ { "packages": ["sandpack-client", "sandpack-react"], - "sandboxes": ["sowx8r"], + "sandboxes": ["sowx8r", "909l3f"], "node": "16" } diff --git a/sandpack-react/src/contexts/utils/useClient.ts b/sandpack-react/src/contexts/utils/useClient.ts index 95ccc1a47..8270e359b 100644 --- a/sandpack-react/src/contexts/utils/useClient.ts +++ b/sandpack-react/src/contexts/utils/useClient.ts @@ -506,6 +506,8 @@ export const useClient: UseClient = (props, filesState) => { [filesState.files, filesState.environment, updateClients] ); + console.log(filesState); + useEffect( function watchInitMode() { if (initModeFromProps !== state.initMode) { From 62adf605112cbe9c5d3bd4e545fc83b2669acf61 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 10:39:05 +0000 Subject: [PATCH 02/26] Update useClient.ts --- .../src/contexts/utils/useClient.ts | 59 ++++++++----------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useClient.ts b/sandpack-react/src/contexts/utils/useClient.ts index 8270e359b..a467a2b24 100644 --- a/sandpack-react/src/contexts/utils/useClient.ts +++ b/sandpack-react/src/contexts/utils/useClient.ts @@ -66,6 +66,9 @@ type UseClient = ( ) => [SandpackConfigState, UseClientOperations]; export const useClient: UseClient = (props, filesState) => { + props.options ??= {}; + props.customSetup ??= {}; + const initModeFromProps = props.options?.initMode || "lazy"; const [state, setState] = useState({ @@ -106,6 +109,9 @@ export const useClient: UseClient = (props, filesState) => { iframe: HTMLIFrameElement, clientId: string ): Promise => { + props.options ??= {}; + props.customSetup ??= {}; + const timeOut = props.options?.bundlerTimeOut ?? BUNDLER_TIMEOUT; if (timeoutHook.current) { @@ -123,17 +129,17 @@ export const useClient: UseClient = (props, filesState) => { template: filesState.environment, }, { - externalResources: props.options?.externalResources, - bundlerURL: props.options?.bundlerURL, - startRoute: props.options?.startRoute, - fileResolver: props.options?.fileResolver, - skipEval: props.options?.skipEval ?? false, - logLevel: props.options?.logLevel, + externalResources: props.options.externalResources, + bundlerURL: props.options.bundlerURL, + startRoute: props.options.startRoute, + fileResolver: props.options.fileResolver, + skipEval: props.options.skipEval ?? false, + logLevel: props.options.logLevel, showOpenInCodeSandbox: false, showErrorScreen: errorScreenRegisteredRef.current, showLoadingScreen: loadingScreenRegisteredRef.current, reactDevTools: state.reactDevTools, - customNpmRegistries: props.customSetup?.npmRegistries?.map( + customNpmRegistries: props.customSetup.npmRegistries?.map( (config) => ({ ...config, @@ -187,18 +193,7 @@ export const useClient: UseClient = (props, filesState) => { return client; }, - [ - filesState.environment, - filesState.files, - props.customSetup?.npmRegistries, - props.options?.bundlerURL, - props.options?.externalResources, - props.options?.fileResolver, - props.options?.logLevel, - props.options?.skipEval, - props.options?.startRoute, - state.reactDevTools, - ] + [filesState.environment, filesState.files, props, state.reactDevTools] ); const unregisterAllClients = useCallback((): void => { @@ -285,16 +280,16 @@ export const useClient: UseClient = (props, filesState) => { unregisterAllClients, ]); - const registerBundler = async ( - iframe: HTMLIFrameElement, - clientId: string - ): Promise => { - if (state.status === "running") { - clients.current[clientId] = await createClient(iframe, clientId); - } else { - preregisteredIframes.current[clientId] = iframe; - } - }; + const registerBundler = useCallback( + async (iframe: HTMLIFrameElement, clientId: string): Promise => { + if (state.status === "running") { + clients.current[clientId] = await createClient(iframe, clientId); + } else { + preregisteredIframes.current[clientId] = iframe; + } + }, + [createClient, state.status] + ); const unregisterBundler = (clientId: string): void => { const client = clients.current[clientId]; @@ -396,13 +391,11 @@ export const useClient: UseClient = (props, filesState) => { }, recompileDelay); } }, [ - filesState.shouldUpdatePreview, - filesState.files, - filesState.environment, + filesState, recompileMode, recompileDelay, state.status, - createClient, + registerBundler, ]); const dispatchMessage = ( From e48c9c2d1f046efff2f5fb2dc7da9f80ca287ec9 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 10:52:06 +0000 Subject: [PATCH 03/26] Update Playground.stories.tsx and useClient.ts --- sandpack-react/src/Playground.stories.tsx | 343 +----------------- .../src/contexts/utils/useClient.ts | 144 ++++---- 2 files changed, 73 insertions(+), 414 deletions(-) diff --git a/sandpack-react/src/Playground.stories.tsx b/sandpack-react/src/Playground.stories.tsx index d42734b9f..ef311306b 100644 --- a/sandpack-react/src/Playground.stories.tsx +++ b/sandpack-react/src/Playground.stories.tsx @@ -1,352 +1,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import * as themes from "@codesandbox/sandpack-themes"; -import React, { useState } from "react"; +import React from "react"; -import type { CodeEditorProps } from "./components/CodeEditor"; import { Sandpack } from "./presets"; -import { SANDBOX_TEMPLATES } from "./templates"; - -import { - SandpackProvider, - SandpackCodeEditor, - SandpackPreview, - SandpackLayout, - SandpackFileExplorer, - SandpackConsole, - SandpackTests, -} from "./"; export default { title: "Intro/Playground", }; -export const Resizable = (): JSX.Element => { - return ( - <> -
- -
-
-
- Modern building architecture -
-
-
- Company retreats -
- - Incredible accommodation for your team - -

- Looking to take your team away on a retreat to enjoy awesome food - and take in some sunshine? We have a list of places to do just that. -

- - -
-
-
-
- ); -}`, - }} - options={{ - externalResources: ["https://cdn.tailwindcss.com"], - showLineNumbers: true, - showConsole: false, - showConsoleButton: true, - resizablePanels: true, - editorHeight: 700, - }} - template="react" - /> - - - ); -}; - -export const Main = (): JSX.Element => { - const [config, setConfig] = useState({ - Components: { - Preview: true, - Editor: true, - FileExplorer: true, - Console: true, - Tests: true, - }, - Options: { - showTabs: true, - showLineNumbers: true, - showInlineErrors: true, - closableTabs: true, - wrapContent: false, - readOnly: false, - showReadOnly: true, - showNavigator: true, - showRefreshButton: true, - consoleShowHeader: true, - showConsoleButton: true, - showConsole: true, - }, - Template: "exhaustedFilesTests" as const, - Theme: "light", - }); - - const update = (key: any, value: any): void => { - setConfig((prev) => ({ ...prev, [key]: value })); - }; - - const toggle = (key: any, value: any): void => { - setConfig((prev) => { - return { - ...prev, - [key]: { ...prev[key], [value]: !prev[key][value] }, - }; - }); - }; - - const codeEditorOptions: CodeEditorProps = { - showTabs: config.Options.showTabs, - showLineNumbers: config.Options.showLineNumbers, - showInlineErrors: config.Options.showInlineErrors, - wrapContent: config.Options.wrapContent, - closableTabs: config.Options.closableTabs, - readOnly: config.Options.readOnly, - showReadOnly: config.Options.showReadOnly, - }; - - return ( -
-
- {Object.entries(config).map(([key, value]) => { - if (typeof value === "string") { - if (key === "Template") { - return ( -
-

Template

- -
- ); - } - - if (key === "Theme") { - return ( -
-

Themes

- -
- ); - } - - return value; - } - - return ( - <> -

{key}

- {Object.entries(value).map(([prop, propValue]) => { - return ( -

- -

- ); - })} - - ); - })} -
- -
- - -
- {config.Components.FileExplorer && } - {config.Components.Editor && ( - - )} - {config.Components.Preview && ( - - )} - - {config.Components.Console && ( - - )} - {config.Components.Tests && } -
-
-
- -
- - -
-
- ); -}; - -const defaultTemplate = SANDBOX_TEMPLATES["react-ts"]; - -const exhaustedFilesTests = { - ...defaultTemplate, - - files: { - "/src/index.tsx": defaultTemplate.files["/index.tsx"], - "/src/App.tsx": `console.log("Hello world");\n\n${defaultTemplate.files["/App.tsx"].code}`, - "/src/App.test.tsx": `import '@testing-library/jest-dom'; -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders welcome message', () => { - render(); - expect(screen.getByText('Hello world')).toBeInTheDocument(); -});`, - "/src/styles.css": defaultTemplate.files["/styles.css"], - "/package.json": JSON.stringify({ - dependencies: { - react: "^18.0.0", - "react-dom": "^18.0.0", - "react-scripts": "^4.0.0", - "@testing-library/react": "^13.3.0", - "@testing-library/jest-dom": "^5.16.5", - }, - devDependencies: { - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - typescript: "^4.0.0", - }, - main: "/add.ts", - }), - }, -}; - -export const BasicConsole: React.FC = () => { - const files = { - "/index.js": `const helloWorld = ""; - -console.log("foo");`, - - "/.eslintrc.js": `module.exports = { - rules: { - "no-unused-vars": "error", - "no-console": "error", - }, - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module' - }, -} -`, - - "/package.json": JSON.stringify({ - devDependencies: { - eslint: "^8.0.1", - }, - scripts: { start: "eslint index.js" }, - }), - }; - - return ( - - - - - - - ); -}; - export const Basic: React.FC = () => { - return ; + return ; }; diff --git a/sandpack-react/src/contexts/utils/useClient.ts b/sandpack-react/src/contexts/utils/useClient.ts index a467a2b24..55f58879b 100644 --- a/sandpack-react/src/contexts/utils/useClient.ts +++ b/sandpack-react/src/contexts/utils/useClient.ts @@ -65,19 +65,19 @@ type UseClient = ( filesState: FilesState ) => [SandpackConfigState, UseClientOperations]; -export const useClient: UseClient = (props, filesState) => { - props.options ??= {}; - props.customSetup ??= {}; +export const useClient: UseClient = ({ options, customSetup }, filesState) => { + options ??= {}; + customSetup ??= {}; - const initModeFromProps = props.options?.initMode || "lazy"; + const initModeFromProps = options?.initMode || "lazy"; const [state, setState] = useState({ - startRoute: props.options?.startRoute, + startRoute: options?.startRoute, bundlerState: undefined, error: null, initMode: initModeFromProps, reactDevTools: undefined, - status: props.options?.autorun ?? true ? "initial" : "idle", + status: options?.autorun ?? true ? "initial" : "idle", }); /** @@ -109,10 +109,10 @@ export const useClient: UseClient = (props, filesState) => { iframe: HTMLIFrameElement, clientId: string ): Promise => { - props.options ??= {}; - props.customSetup ??= {}; + options ??= {}; + customSetup ??= {}; - const timeOut = props.options?.bundlerTimeOut ?? BUNDLER_TIMEOUT; + const timeOut = options?.bundlerTimeOut ?? BUNDLER_TIMEOUT; if (timeoutHook.current) { clearTimeout(timeoutHook.current); @@ -129,17 +129,17 @@ export const useClient: UseClient = (props, filesState) => { template: filesState.environment, }, { - externalResources: props.options.externalResources, - bundlerURL: props.options.bundlerURL, - startRoute: props.options.startRoute, - fileResolver: props.options.fileResolver, - skipEval: props.options.skipEval ?? false, - logLevel: props.options.logLevel, + externalResources: options.externalResources, + bundlerURL: options.bundlerURL, + startRoute: options.startRoute, + fileResolver: options.fileResolver, + skipEval: options.skipEval ?? false, + logLevel: options.logLevel, showOpenInCodeSandbox: false, showErrorScreen: errorScreenRegisteredRef.current, showLoadingScreen: loadingScreenRegisteredRef.current, reactDevTools: state.reactDevTools, - customNpmRegistries: props.customSetup.npmRegistries?.map( + customNpmRegistries: customSetup.npmRegistries?.map( (config) => ({ ...config, @@ -193,7 +193,7 @@ export const useClient: UseClient = (props, filesState) => { return client; }, - [filesState.environment, filesState.files, props, state.reactDevTools] + [filesState.environment, filesState.files, state.reactDevTools] ); const unregisterAllClients = useCallback((): void => { @@ -217,13 +217,13 @@ export const useClient: UseClient = (props, filesState) => { }, [createClient]); const initializeSandpackIframe = useCallback((): void => { - const autorun = props.options?.autorun ?? true; + const autorun = options?.autorun ?? true; if (!autorun) { return; } - const observerOptions = props.options?.initModeObserverOptions ?? { + const observerOptions = options?.initModeObserverOptions ?? { rootMargin: `1000px 0px`, }; @@ -273,8 +273,8 @@ export const useClient: UseClient = (props, filesState) => { ); } }, [ - props.options?.autorun, - props.options?.initModeObserverOptions, + options?.autorun, + options?.initModeObserverOptions, runSandpack, state.initMode, unregisterAllClients, @@ -349,54 +349,8 @@ export const useClient: UseClient = (props, filesState) => { setState((prev) => ({ ...prev, reactDevTools: value })); }; - const recompileMode = props.options?.recompileMode ?? "delayed"; - const recompileDelay = props.options?.recompileDelay ?? 500; - const updateClients = useCallback((): void => { - if (state.status !== "running" || !filesState.shouldUpdatePreview) { - return; - } - - /** - * When the environment changes, Sandpack needs to make sure - * to create a new client and the proper bundler - */ - if (prevEnvironment.current !== filesState.environment) { - prevEnvironment.current = filesState.environment; - - Object.entries(clients.current).forEach(([key, client]) => { - registerBundler(client.iframe, key); - }); - } - - if (recompileMode === "immediate") { - Object.values(clients.current).forEach((client) => { - client.updateSandbox({ - files: filesState.files, - template: filesState.environment, - }); - }); - } - - if (recompileMode === "delayed") { - if (typeof window === "undefined") return; - - window.clearTimeout(debounceHook.current); - debounceHook.current = window.setTimeout(() => { - Object.values(clients.current).forEach((client) => { - client.updateSandbox({ - files: filesState.files, - template: filesState.environment, - }); - }); - }, recompileDelay); - } - }, [ - filesState, - recompileMode, - recompileDelay, - state.status, - registerBundler, - ]); + const recompileMode = options?.recompileMode ?? "delayed"; + const recompileDelay = options?.recompileDelay ?? 500; const dispatchMessage = ( message: SandpackMessage, @@ -492,15 +446,59 @@ export const useClient: UseClient = (props, filesState) => { /** * Effects */ + useEffect( function watchFileChanges() { - updateClients(); + if (state.status !== "running" || !filesState.shouldUpdatePreview) { + return; + } + + /** + * When the environment changes, Sandpack needs to make sure + * to create a new client and the proper bundler + */ + if (prevEnvironment.current !== filesState.environment) { + prevEnvironment.current = filesState.environment; + + Object.entries(clients.current).forEach(([key, client]) => { + registerBundler(client.iframe, key); + }); + } + + if (recompileMode === "immediate") { + Object.values(clients.current).forEach((client) => { + client.updateSandbox({ + files: filesState.files, + template: filesState.environment, + }); + }); + } + + if (recompileMode === "delayed") { + if (typeof window === "undefined") return; + + window.clearTimeout(debounceHook.current); + debounceHook.current = window.setTimeout(() => { + Object.values(clients.current).forEach((client) => { + client.updateSandbox({ + files: filesState.files, + template: filesState.environment, + }); + }); + }, recompileDelay); + } }, - [filesState.files, filesState.environment, updateClients] + [ + filesState.files, + filesState.environment, + filesState.shouldUpdatePreview, + recompileDelay, + recompileMode, + registerBundler, + state.status, + ] ); - console.log(filesState); - useEffect( function watchInitMode() { if (initModeFromProps !== state.initMode) { From 63029bb2f78bdbe0b779dc313583f10119c29c8c Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:08:17 +0000 Subject: [PATCH 04/26] Update ci.json and Playground.stories.tsx --- .codesandbox/ci.json | 2 +- sandpack-react/src/Playground.stories.tsx | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index fabf52bc2..f2ca469a6 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,5 +1,5 @@ { "packages": ["sandpack-client", "sandpack-react"], - "sandboxes": ["sowx8r", "909l3f"], + "sandboxes": ["sowx8r", "3zr6t8"], "node": "16" } diff --git a/sandpack-react/src/Playground.stories.tsx b/sandpack-react/src/Playground.stories.tsx index ef311306b..19a211578 100644 --- a/sandpack-react/src/Playground.stories.tsx +++ b/sandpack-react/src/Playground.stories.tsx @@ -9,5 +9,23 @@ export default { }; export const Basic: React.FC = () => { - return ; + const [text, setText] = React.useState("world"); + return ( + <> + setText(target.value)} + /> + Hello ${text} +} +`, + }} + template="react" + theme={themes.sandpackDark} + /> + + ); }; From d24102a6c0429f43eb8499f29a48c80b69869e9d Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:09:26 +0000 Subject: [PATCH 05/26] Update sandpackContext.tsx and useClient.ts --- sandpack-react/src/contexts/sandpackContext.tsx | 1 + sandpack-react/src/contexts/utils/useClient.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sandpack-react/src/contexts/sandpackContext.tsx b/sandpack-react/src/contexts/sandpackContext.tsx index 6b458d5b1..08e592f9e 100644 --- a/sandpack-react/src/contexts/sandpackContext.tsx +++ b/sandpack-react/src/contexts/sandpackContext.tsx @@ -14,6 +14,7 @@ export const SandpackProvider: React.FC = (props) => { const { children, options, style, className, theme } = props; const [fileState, fileOperations] = useFiles(props); + console.log("SandpackProvider", fileState); const [clientState, { dispatchMessage, addListener, ...clientOperations }] = useClient(props, fileState); const appState = useAppState(props, fileState.files); diff --git a/sandpack-react/src/contexts/utils/useClient.ts b/sandpack-react/src/contexts/utils/useClient.ts index 55f58879b..6bb9038ce 100644 --- a/sandpack-react/src/contexts/utils/useClient.ts +++ b/sandpack-react/src/contexts/utils/useClient.ts @@ -69,6 +69,8 @@ export const useClient: UseClient = ({ options, customSetup }, filesState) => { options ??= {}; customSetup ??= {}; + console.log("useClient", filesState); + const initModeFromProps = options?.initMode || "lazy"; const [state, setState] = useState({ From babde2374a55ba8352b7f7f59abe1ab348700107 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:13:34 +0000 Subject: [PATCH 06/26] Update sandpackContext.tsx and useClient.ts --- sandpack-react/src/components/CodeEditor/CodeMirror.tsx | 1 + sandpack-react/src/contexts/sandpackContext.tsx | 2 +- sandpack-react/src/contexts/utils/useClient.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sandpack-react/src/components/CodeEditor/CodeMirror.tsx b/sandpack-react/src/components/CodeEditor/CodeMirror.tsx index 2df705147..c4b8e3f48 100644 --- a/sandpack-react/src/components/CodeEditor/CodeMirror.tsx +++ b/sandpack-react/src/components/CodeEditor/CodeMirror.tsx @@ -288,6 +288,7 @@ export const CodeMirror = React.forwardRef( const newCode = tr.newDoc.sliceString(0, tr.newDoc.length); setInternalCode(newCode); + console.log("onCodeUpdate", newCode); onCodeUpdate?.(newCode); } }, diff --git a/sandpack-react/src/contexts/sandpackContext.tsx b/sandpack-react/src/contexts/sandpackContext.tsx index 08e592f9e..7883ec2b3 100644 --- a/sandpack-react/src/contexts/sandpackContext.tsx +++ b/sandpack-react/src/contexts/sandpackContext.tsx @@ -14,7 +14,7 @@ export const SandpackProvider: React.FC = (props) => { const { children, options, style, className, theme } = props; const [fileState, fileOperations] = useFiles(props); - console.log("SandpackProvider", fileState); + console.log("SandpackProvider", fileState.files["/App.js"]); const [clientState, { dispatchMessage, addListener, ...clientOperations }] = useClient(props, fileState); const appState = useAppState(props, fileState.files); diff --git a/sandpack-react/src/contexts/utils/useClient.ts b/sandpack-react/src/contexts/utils/useClient.ts index 6bb9038ce..660d768fe 100644 --- a/sandpack-react/src/contexts/utils/useClient.ts +++ b/sandpack-react/src/contexts/utils/useClient.ts @@ -69,7 +69,7 @@ export const useClient: UseClient = ({ options, customSetup }, filesState) => { options ??= {}; customSetup ??= {}; - console.log("useClient", filesState); + console.log("useClient", filesState.files["/App.js"]); const initModeFromProps = options?.initMode || "lazy"; From e5e90f7f636d803dbde16425d3131801cc9994f3 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:17:54 +0000 Subject: [PATCH 07/26] Update 3 files --- sandpack-react/src/contexts/sandpackContext.tsx | 2 +- sandpack-react/src/contexts/utils/useClient.ts | 2 +- sandpack-react/src/contexts/utils/useFiles.ts | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sandpack-react/src/contexts/sandpackContext.tsx b/sandpack-react/src/contexts/sandpackContext.tsx index 7883ec2b3..5ca47efdb 100644 --- a/sandpack-react/src/contexts/sandpackContext.tsx +++ b/sandpack-react/src/contexts/sandpackContext.tsx @@ -14,7 +14,7 @@ export const SandpackProvider: React.FC = (props) => { const { children, options, style, className, theme } = props; const [fileState, fileOperations] = useFiles(props); - console.log("SandpackProvider", fileState.files["/App.js"]); + console.log("SandpackProvider", fileState.files["/App.js"].code); const [clientState, { dispatchMessage, addListener, ...clientOperations }] = useClient(props, fileState); const appState = useAppState(props, fileState.files); diff --git a/sandpack-react/src/contexts/utils/useClient.ts b/sandpack-react/src/contexts/utils/useClient.ts index 660d768fe..213fd171b 100644 --- a/sandpack-react/src/contexts/utils/useClient.ts +++ b/sandpack-react/src/contexts/utils/useClient.ts @@ -69,7 +69,7 @@ export const useClient: UseClient = ({ options, customSetup }, filesState) => { options ??= {}; customSetup ??= {}; - console.log("useClient", filesState.files["/App.js"]); + console.log("useClient", filesState.files["/App.js"].code); const initModeFromProps = options?.initMode || "lazy"; diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index f89045529..89123d656 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -65,6 +65,8 @@ export const useFiles: UseFiles = (props) => { if (filesHaveChanged) { setState(originalStateFromProps); + console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); + prevOriginalStateFromProps.current = originalStateFromProps; } @@ -185,6 +187,8 @@ export const useFiles: UseFiles = (props) => { }, }; + console.log("useFiles > root", state.files["/App.js"].code); + return [ { ...state, visibleFilesFromProps: originalStateFromProps.visibleFiles }, operations, From c2aa750d42ec654d554465e51ae51e3bfb84109e Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:25:34 +0000 Subject: [PATCH 08/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 89123d656..bd3b699b3 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -54,21 +54,37 @@ export type UseFiles = (props: SandpackProviderProps) => [ export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); - const prevOriginalStateFromProps = useRef(originalStateFromProps); + // const prevOriginalStateFromProps = useRef(originalStateFromProps); const [state, setState] = useState(originalStateFromProps); - const filesHaveChanged = !isEqual( - prevOriginalStateFromProps.current, - originalStateFromProps - ); - if (filesHaveChanged) { - setState(originalStateFromProps); + // const filesHaveChanged = !isEqual( + // prevOriginalStateFromProps.current, + // originalStateFromProps + // ); - console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); + // if (filesHaveChanged) { + // setState(originalStateFromProps); - prevOriginalStateFromProps.current = originalStateFromProps; - } + // console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); + + // prevOriginalStateFromProps.current = originalStateFromProps; + // } + + // useEffect(() => { + // const filesHaveChanged = !isEqual( + // prevOriginalStateFromProps.current, + // originalStateFromProps + // ); + + // if (filesHaveChanged) { + // setState(originalStateFromProps); + + // console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); + + // prevOriginalStateFromProps.current = originalStateFromProps; + // } + // }, [originalStateFromProps, state.files]); const updateFile = ( pathOrFiles: string | SandpackFiles, From 400f402fe44cccb0faa7b94e511f941fa4cee629 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:26:40 +0000 Subject: [PATCH 09/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index bd3b699b3..d8b48b6ba 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -58,18 +58,13 @@ export const useFiles: UseFiles = (props) => { const [state, setState] = useState(originalStateFromProps); - // const filesHaveChanged = !isEqual( - // prevOriginalStateFromProps.current, - // originalStateFromProps - // ); + const filesHaveChanged = !isEqual(originalStateFromProps, state); - // if (filesHaveChanged) { - // setState(originalStateFromProps); + if (filesHaveChanged) { + setState(originalStateFromProps); - // console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); - - // prevOriginalStateFromProps.current = originalStateFromProps; - // } + console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); + } // useEffect(() => { // const filesHaveChanged = !isEqual( From 4d39bd1373825e75d7fb5c704bac53ee51eb9195 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:30:05 +0000 Subject: [PATCH 10/26] Update 3 files --- .../src/components/CodeEditor/CodeMirror.tsx | 2 +- .../src/contexts/sandpackContext.tsx | 2 +- .../src/contexts/utils/useClient.ts | 2 -- sandpack-react/src/contexts/utils/useFiles.ts | 21 +------------------ 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/sandpack-react/src/components/CodeEditor/CodeMirror.tsx b/sandpack-react/src/components/CodeEditor/CodeMirror.tsx index c4b8e3f48..738857968 100644 --- a/sandpack-react/src/components/CodeEditor/CodeMirror.tsx +++ b/sandpack-react/src/components/CodeEditor/CodeMirror.tsx @@ -288,7 +288,7 @@ export const CodeMirror = React.forwardRef( const newCode = tr.newDoc.sliceString(0, tr.newDoc.length); setInternalCode(newCode); - console.log("onCodeUpdate", newCode); + onCodeUpdate?.(newCode); } }, diff --git a/sandpack-react/src/contexts/sandpackContext.tsx b/sandpack-react/src/contexts/sandpackContext.tsx index 5ca47efdb..8cf400b0a 100644 --- a/sandpack-react/src/contexts/sandpackContext.tsx +++ b/sandpack-react/src/contexts/sandpackContext.tsx @@ -14,7 +14,7 @@ export const SandpackProvider: React.FC = (props) => { const { children, options, style, className, theme } = props; const [fileState, fileOperations] = useFiles(props); - console.log("SandpackProvider", fileState.files["/App.js"].code); + const [clientState, { dispatchMessage, addListener, ...clientOperations }] = useClient(props, fileState); const appState = useAppState(props, fileState.files); diff --git a/sandpack-react/src/contexts/utils/useClient.ts b/sandpack-react/src/contexts/utils/useClient.ts index 213fd171b..55f58879b 100644 --- a/sandpack-react/src/contexts/utils/useClient.ts +++ b/sandpack-react/src/contexts/utils/useClient.ts @@ -69,8 +69,6 @@ export const useClient: UseClient = ({ options, customSetup }, filesState) => { options ??= {}; customSetup ??= {}; - console.log("useClient", filesState.files["/App.js"].code); - const initModeFromProps = options?.initMode || "lazy"; const [state, setState] = useState({ diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index d8b48b6ba..88643feb0 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; import isEqual from "lodash.isequal"; -import { useRef, useState } from "react"; +import { useState } from "react"; import type { SandboxEnvironment, @@ -62,25 +62,8 @@ export const useFiles: UseFiles = (props) => { if (filesHaveChanged) { setState(originalStateFromProps); - - console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); } - // useEffect(() => { - // const filesHaveChanged = !isEqual( - // prevOriginalStateFromProps.current, - // originalStateFromProps - // ); - - // if (filesHaveChanged) { - // setState(originalStateFromProps); - - // console.log("useFiles > filesHaveChanged", state.files["/App.js"].code); - - // prevOriginalStateFromProps.current = originalStateFromProps; - // } - // }, [originalStateFromProps, state.files]); - const updateFile = ( pathOrFiles: string | SandpackFiles, code?: string, @@ -198,8 +181,6 @@ export const useFiles: UseFiles = (props) => { }, }; - console.log("useFiles > root", state.files["/App.js"].code); - return [ { ...state, visibleFilesFromProps: originalStateFromProps.visibleFiles }, operations, From 9f1fdce440e2fc51e0616ceb4a0f737ffb35ac08 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:30:36 +0000 Subject: [PATCH 11/26] Update ci.json --- .codesandbox/ci.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index f2ca469a6..fabf52bc2 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,5 +1,5 @@ { "packages": ["sandpack-client", "sandpack-react"], - "sandboxes": ["sowx8r", "3zr6t8"], + "sandboxes": ["sowx8r", "909l3f"], "node": "16" } From f4274c869390007ac1f0f127646d25b44024aea1 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:32:09 +0000 Subject: [PATCH 12/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 88643feb0..1f93ecf80 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -54,12 +54,9 @@ export type UseFiles = (props: SandpackProviderProps) => [ export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); - // const prevOriginalStateFromProps = useRef(originalStateFromProps); - const [state, setState] = useState(originalStateFromProps); const filesHaveChanged = !isEqual(originalStateFromProps, state); - if (filesHaveChanged) { setState(originalStateFromProps); } From c5ed395513a9599520f613e8d65b3f355b4ae16d Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 11:59:52 +0000 Subject: [PATCH 13/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 1f93ecf80..3fa1a41e3 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; import isEqual from "lodash.isequal"; -import { useState } from "react"; +import { useState, useRef } from "react"; import type { SandboxEnvironment, @@ -53,12 +53,18 @@ export type UseFiles = (props: SandpackProviderProps) => [ ]; export const useFiles: UseFiles = (props) => { - const originalStateFromProps = getSandpackStateFromProps(props); - const [state, setState] = useState(originalStateFromProps); - - const filesHaveChanged = !isEqual(originalStateFromProps, state); + const originalStateFromProps = useRef(getSandpackStateFromProps(props)); + const [state, setState] = useState( + getSandpackStateFromProps(props) + ); + + const filesHaveChanged = !isEqual( + originalStateFromProps.current, + getSandpackStateFromProps(props) + ); if (filesHaveChanged) { - setState(originalStateFromProps); + setState(getSandpackStateFromProps(props)); + originalStateFromProps.current = getSandpackStateFromProps(props); } const updateFile = ( @@ -105,12 +111,15 @@ export const useFiles: UseFiles = (props) => { ...prevState, files: { ...prevState.files, - [path]: originalStateFromProps.files[path], + [path]: originalStateFromProps.current.files[path], }, })); }, resetAllFiles: (): void => { - setState((prev) => ({ ...prev, files: originalStateFromProps.files })); + setState((prev) => ({ + ...prev, + files: originalStateFromProps.current.files, + })); }, setActiveFile: (activeFile: string): void => { if (state.files[activeFile]) { @@ -179,7 +188,10 @@ export const useFiles: UseFiles = (props) => { }; return [ - { ...state, visibleFilesFromProps: originalStateFromProps.visibleFiles }, + { + ...state, + visibleFilesFromProps: originalStateFromProps.current.visibleFiles, + }, operations, ]; }; From 5c485fd4e1439866fb3131947a736180109bf3b8 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 13:24:24 +0000 Subject: [PATCH 14/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 3fa1a41e3..7ea90ec9b 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; import isEqual from "lodash.isequal"; -import { useState, useRef } from "react"; +import { useState, useRef, useEffect } from "react"; import type { SandboxEnvironment, @@ -52,19 +52,27 @@ export type UseFiles = (props: SandpackProviderProps) => [ FilesOperations ]; +/* eslint-disable @typescript-eslint/no-explicit-any */ +function usePrevious(value: any) { + const ref = useRef(); + useEffect(() => { + ref.current = value; + }, [value]); + return ref.current; +} + export const useFiles: UseFiles = (props) => { - const originalStateFromProps = useRef(getSandpackStateFromProps(props)); - const [state, setState] = useState( - getSandpackStateFromProps(props) - ); + const originalStateFromProps = getSandpackStateFromProps(props); + const prevOriginalStateFromProps = usePrevious(originalStateFromProps); + + const [state, setState] = useState(originalStateFromProps); const filesHaveChanged = !isEqual( - originalStateFromProps.current, - getSandpackStateFromProps(props) + prevOriginalStateFromProps, + originalStateFromProps ); if (filesHaveChanged) { - setState(getSandpackStateFromProps(props)); - originalStateFromProps.current = getSandpackStateFromProps(props); + setState(originalStateFromProps); } const updateFile = ( @@ -111,14 +119,14 @@ export const useFiles: UseFiles = (props) => { ...prevState, files: { ...prevState.files, - [path]: originalStateFromProps.current.files[path], + [path]: originalStateFromProps.files[path], }, })); }, resetAllFiles: (): void => { setState((prev) => ({ ...prev, - files: originalStateFromProps.current.files, + files: originalStateFromProps.files, })); }, setActiveFile: (activeFile: string): void => { @@ -190,7 +198,7 @@ export const useFiles: UseFiles = (props) => { return [ { ...state, - visibleFilesFromProps: originalStateFromProps.current.visibleFiles, + visibleFilesFromProps: originalStateFromProps.visibleFiles, }, operations, ]; From dfa245e443eac09c7d7b31cc8d9a2da64307368f Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 14:51:45 +0000 Subject: [PATCH 15/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 7ea90ec9b..9891cd9cd 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,6 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; -import isEqual from "lodash.isequal"; -import { useState, useRef, useEffect } from "react"; +import { useState, useEffect } from "react"; import type { SandboxEnvironment, @@ -52,28 +51,15 @@ export type UseFiles = (props: SandpackProviderProps) => [ FilesOperations ]; -/* eslint-disable @typescript-eslint/no-explicit-any */ -function usePrevious(value: any) { - const ref = useRef(); - useEffect(() => { - ref.current = value; - }, [value]); - return ref.current; -} - export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); - const prevOriginalStateFromProps = usePrevious(originalStateFromProps); const [state, setState] = useState(originalStateFromProps); - const filesHaveChanged = !isEqual( - prevOriginalStateFromProps, - originalStateFromProps - ); - if (filesHaveChanged) { + useEffect(() => { + const originalStateFromProps = getSandpackStateFromProps(props); setState(originalStateFromProps); - } + }, [props]); const updateFile = ( pathOrFiles: string | SandpackFiles, From 54b8580dddf48582d20abc5ad4dc189a9d301f25 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 15:20:50 +0000 Subject: [PATCH 16/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 9891cd9cd..2f04c52a4 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,6 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; -import { useState, useEffect } from "react"; +import { isEqual } from "lodash"; +import { useState, useEffect, useRef } from "react"; import type { SandboxEnvironment, @@ -53,13 +54,19 @@ export type UseFiles = (props: SandpackProviderProps) => [ export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); + const prevOriginalStateFromProps = useRef(originalStateFromProps); const [state, setState] = useState(originalStateFromProps); - useEffect(() => { - const originalStateFromProps = getSandpackStateFromProps(props); + const filesHaveChanged = !isEqual( + prevOriginalStateFromProps.current, + originalStateFromProps + ); + if (filesHaveChanged) { + prevOriginalStateFromProps.current = originalStateFromProps; + setState(originalStateFromProps); - }, [props]); + } const updateFile = ( pathOrFiles: string | SandpackFiles, From 6b9fa19493e0995fd9fe4ff2db542d8c989c0eea Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 15:22:50 +0000 Subject: [PATCH 17/26] Update 3 files --- sandpack-react/src/components/CodeEditor/CodeMirror.tsx | 1 - sandpack-react/src/contexts/sandpackContext.tsx | 1 - sandpack-react/src/contexts/utils/useFiles.ts | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sandpack-react/src/components/CodeEditor/CodeMirror.tsx b/sandpack-react/src/components/CodeEditor/CodeMirror.tsx index 738857968..2df705147 100644 --- a/sandpack-react/src/components/CodeEditor/CodeMirror.tsx +++ b/sandpack-react/src/components/CodeEditor/CodeMirror.tsx @@ -288,7 +288,6 @@ export const CodeMirror = React.forwardRef( const newCode = tr.newDoc.sliceString(0, tr.newDoc.length); setInternalCode(newCode); - onCodeUpdate?.(newCode); } }, diff --git a/sandpack-react/src/contexts/sandpackContext.tsx b/sandpack-react/src/contexts/sandpackContext.tsx index 8cf400b0a..6b458d5b1 100644 --- a/sandpack-react/src/contexts/sandpackContext.tsx +++ b/sandpack-react/src/contexts/sandpackContext.tsx @@ -14,7 +14,6 @@ export const SandpackProvider: React.FC = (props) => { const { children, options, style, className, theme } = props; const [fileState, fileOperations] = useFiles(props); - const [clientState, { dispatchMessage, addListener, ...clientOperations }] = useClient(props, fileState); const appState = useAppState(props, fileState.files); diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 2f04c52a4..0fdccadc4 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; -import { isEqual } from "lodash"; -import { useState, useEffect, useRef } from "react"; +import isEqual from "lodash.isequal"; +import { useState, useRef } from "react"; import type { SandboxEnvironment, From 294b053ef5bc3435bbac6c90e7b261c6c486588e Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 15:26:03 +0000 Subject: [PATCH 18/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 0fdccadc4..705280b80 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; import isEqual from "lodash.isequal"; -import { useState, useRef } from "react"; +import { useRef, useState } from "react"; import type { SandboxEnvironment, @@ -54,7 +54,7 @@ export type UseFiles = (props: SandpackProviderProps) => [ export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); - const prevOriginalStateFromProps = useRef(originalStateFromProps); + const prevOriginalStateFromProps = useRef({ ...originalStateFromProps }); const [state, setState] = useState(originalStateFromProps); @@ -117,10 +117,7 @@ export const useFiles: UseFiles = (props) => { })); }, resetAllFiles: (): void => { - setState((prev) => ({ - ...prev, - files: originalStateFromProps.files, - })); + setState((prev) => ({ ...prev, files: originalStateFromProps.files })); }, setActiveFile: (activeFile: string): void => { if (state.files[activeFile]) { @@ -189,10 +186,7 @@ export const useFiles: UseFiles = (props) => { }; return [ - { - ...state, - visibleFilesFromProps: originalStateFromProps.visibleFiles, - }, + { ...state, visibleFilesFromProps: originalStateFromProps.visibleFiles }, operations, ]; }; From 3b428b8d6a3cb643f4003fcf42877946055fb625 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 15:27:59 +0000 Subject: [PATCH 19/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 705280b80..fe116e0e6 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -54,9 +54,9 @@ export type UseFiles = (props: SandpackProviderProps) => [ export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); - const prevOriginalStateFromProps = useRef({ ...originalStateFromProps }); + const prevOriginalStateFromProps = useRef(originalStateFromProps); - const [state, setState] = useState(originalStateFromProps); + const [state, setState] = useState({ ...originalStateFromProps }); const filesHaveChanged = !isEqual( prevOriginalStateFromProps.current, From 7dbc902f4afff46d17590399c4ea406c067d8a18 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 15:33:30 +0000 Subject: [PATCH 20/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index fe116e0e6..4270c8040 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -56,7 +56,16 @@ export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); const prevOriginalStateFromProps = useRef(originalStateFromProps); - const [state, setState] = useState({ ...originalStateFromProps }); + const [state, setState] = useState( + prevOriginalStateFromProps.current + ); + + console.log({ + local: "before", + originalStateFromProps, + prevOriginalStateFromProps: prevOriginalStateFromProps.current, + state, + }); const filesHaveChanged = !isEqual( prevOriginalStateFromProps.current, @@ -65,9 +74,23 @@ export const useFiles: UseFiles = (props) => { if (filesHaveChanged) { prevOriginalStateFromProps.current = originalStateFromProps; + console.log({ + local: "conditional", + originalStateFromProps, + prevOriginalStateFromProps: prevOriginalStateFromProps.current, + state, + }); + setState(originalStateFromProps); } + console.log({ + local: "after", + originalStateFromProps, + prevOriginalStateFromProps: prevOriginalStateFromProps.current, + state, + }); + const updateFile = ( pathOrFiles: string | SandpackFiles, code?: string, From b1e75ddc9a80cfc30895f2355187c30a8eb5c8ab Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 15:42:49 +0000 Subject: [PATCH 21/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 4270c8040..3cb7f644e 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -118,6 +118,7 @@ export const useFiles: UseFiles = (props) => { const operations = { openFile: (path: string): void => { + console.log("openFile"); setState(({ visibleFiles, ...rest }) => { const newPaths = visibleFiles.includes(path) ? visibleFiles @@ -131,6 +132,7 @@ export const useFiles: UseFiles = (props) => { }); }, resetFile: (path: string): void => { + console.log("resetFile"); setState((prevState) => ({ ...prevState, files: { @@ -140,19 +142,23 @@ export const useFiles: UseFiles = (props) => { })); }, resetAllFiles: (): void => { + console.log("resetAllFiles"); setState((prev) => ({ ...prev, files: originalStateFromProps.files })); }, setActiveFile: (activeFile: string): void => { + console.log("setActiveFile"); if (state.files[activeFile]) { setState((prev) => ({ ...prev, activeFile })); } }, updateCurrentFile: (code: string): void => { + console.log("updateCurrentFile"); updateFile(state.activeFile, code); }, updateFile, addFile: updateFile, closeFile: (path: string): void => { + console.log("closeFile"); if (state.visibleFiles.length === 1) { return; } @@ -174,6 +180,7 @@ export const useFiles: UseFiles = (props) => { }); }, deleteFile: (path: string, shouldUpdatePreview = true): void => { + console.log("deleteFile"); setState(({ visibleFiles, files, activeFile, ...rest }) => { const newFiles = { ...files }; delete newFiles[path]; From 765465613493bc49551aa10fd524bc85175deac0 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 15:47:00 +0000 Subject: [PATCH 22/26] Update useFiles.ts --- sandpack-react/src/contexts/utils/useFiles.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index 3cb7f644e..e77d044ec 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -96,6 +96,7 @@ export const useFiles: UseFiles = (props) => { code?: string, shouldUpdatePreview = true ): void => { + console.log("updateFile"); setState((prev) => { let files = prev.files; From 54a8bbd2a123bc38e0f685f345e1103c9d3dfc84 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 16:10:48 +0000 Subject: [PATCH 23/26] Update Console.stories.tsx and useFiles.ts --- .../components/Console/Console.stories.tsx | 3 +- sandpack-react/src/contexts/utils/useFiles.ts | 76 ++++++++----------- 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/sandpack-react/src/components/Console/Console.stories.tsx b/sandpack-react/src/components/Console/Console.stories.tsx index 598334e76..81fc277fc 100644 --- a/sandpack-react/src/components/Console/Console.stories.tsx +++ b/sandpack-react/src/components/Console/Console.stories.tsx @@ -3,7 +3,8 @@ import React from "react"; import { SandpackCodeEditor, SandpackPreview } from ".."; import { SandpackProvider, SandpackLayout, Sandpack } from "../.."; -import { SandpackConsole, SandpackConsoleRef } from "./SandpackConsole"; +import type { SandpackConsoleRef } from "./SandpackConsole"; +import { SandpackConsole } from "./SandpackConsole"; export default { title: "components/Console", diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index e77d044ec..a191a3baa 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; import isEqual from "lodash.isequal"; -import { useRef, useState } from "react"; +import { useState, useEffect, useRef, useMemo } from "react"; import type { SandboxEnvironment, @@ -52,51 +52,38 @@ export type UseFiles = (props: SandpackProviderProps) => [ FilesOperations ]; +export function useDeepCompareMemoize(value: T) { + const ref = useRef(value); + const signalRef = useRef(0); + + if (!isEqual(value, ref.current)) { + ref.current = value; + signalRef.current += 1; + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + return useMemo(() => ref.current, [signalRef.current]); +} + +function useDeepCompareEffect(callback: any, dependencies: any) { + // eslint-disable-next-line react-hooks/exhaustive-deps + return useEffect(callback, useDeepCompareMemoize(dependencies)); +} + export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); - const prevOriginalStateFromProps = useRef(originalStateFromProps); - - const [state, setState] = useState( - prevOriginalStateFromProps.current - ); - - console.log({ - local: "before", - originalStateFromProps, - prevOriginalStateFromProps: prevOriginalStateFromProps.current, - state, - }); - - const filesHaveChanged = !isEqual( - prevOriginalStateFromProps.current, - originalStateFromProps - ); - if (filesHaveChanged) { - prevOriginalStateFromProps.current = originalStateFromProps; - - console.log({ - local: "conditional", - originalStateFromProps, - prevOriginalStateFromProps: prevOriginalStateFromProps.current, - state, - }); - setState(originalStateFromProps); - } + const [state, setState] = useState(originalStateFromProps); - console.log({ - local: "after", - originalStateFromProps, - prevOriginalStateFromProps: prevOriginalStateFromProps.current, - state, - }); + useDeepCompareEffect(() => { + setState(getSandpackStateFromProps(props)); + }, [props]); const updateFile = ( pathOrFiles: string | SandpackFiles, code?: string, shouldUpdatePreview = true ): void => { - console.log("updateFile"); setState((prev) => { let files = prev.files; @@ -119,7 +106,6 @@ export const useFiles: UseFiles = (props) => { const operations = { openFile: (path: string): void => { - console.log("openFile"); setState(({ visibleFiles, ...rest }) => { const newPaths = visibleFiles.includes(path) ? visibleFiles @@ -133,7 +119,6 @@ export const useFiles: UseFiles = (props) => { }); }, resetFile: (path: string): void => { - console.log("resetFile"); setState((prevState) => ({ ...prevState, files: { @@ -143,23 +128,22 @@ export const useFiles: UseFiles = (props) => { })); }, resetAllFiles: (): void => { - console.log("resetAllFiles"); - setState((prev) => ({ ...prev, files: originalStateFromProps.files })); + setState((prev) => ({ + ...prev, + files: originalStateFromProps.files, + })); }, setActiveFile: (activeFile: string): void => { - console.log("setActiveFile"); if (state.files[activeFile]) { setState((prev) => ({ ...prev, activeFile })); } }, updateCurrentFile: (code: string): void => { - console.log("updateCurrentFile"); updateFile(state.activeFile, code); }, updateFile, addFile: updateFile, closeFile: (path: string): void => { - console.log("closeFile"); if (state.visibleFiles.length === 1) { return; } @@ -181,7 +165,6 @@ export const useFiles: UseFiles = (props) => { }); }, deleteFile: (path: string, shouldUpdatePreview = true): void => { - console.log("deleteFile"); setState(({ visibleFiles, files, activeFile, ...rest }) => { const newFiles = { ...files }; delete newFiles[path]; @@ -217,7 +200,10 @@ export const useFiles: UseFiles = (props) => { }; return [ - { ...state, visibleFilesFromProps: originalStateFromProps.visibleFiles }, + { + ...state, + visibleFilesFromProps: originalStateFromProps.visibleFiles, + }, operations, ]; }; From 4ba8351e4bdcf063c06fb74b22f25200e4d0197e Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 16:12:12 +0000 Subject: [PATCH 24/26] Update 3 files --- sandpack-react/package.json | 1 + sandpack-react/src/contexts/utils/useFiles.ts | 22 ++----------------- yarn.lock | 10 ++++++++- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/sandpack-react/package.json b/sandpack-react/package.json index 7e0954d00..cc2e1f533 100644 --- a/sandpack-react/package.json +++ b/sandpack-react/package.json @@ -35,6 +35,7 @@ "README.md" ], "dependencies": { + "use-deep-compare-effect": "1.8.1", "@code-hike/classer": "^0.0.0-aa6efee", "@codemirror/autocomplete": "^6.4.0", "@codemirror/commands": "^6.1.3", diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index a191a3baa..ef8c8659b 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -1,7 +1,7 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; import { normalizePath } from "@codesandbox/sandpack-client"; -import isEqual from "lodash.isequal"; -import { useState, useEffect, useRef, useMemo } from "react"; +import { useState } from "react"; +import useDeepCompareEffect from "use-deep-compare-effect"; import type { SandboxEnvironment, @@ -52,24 +52,6 @@ export type UseFiles = (props: SandpackProviderProps) => [ FilesOperations ]; -export function useDeepCompareMemoize(value: T) { - const ref = useRef(value); - const signalRef = useRef(0); - - if (!isEqual(value, ref.current)) { - ref.current = value; - signalRef.current += 1; - } - - // eslint-disable-next-line react-hooks/exhaustive-deps - return useMemo(() => ref.current, [signalRef.current]); -} - -function useDeepCompareEffect(callback: any, dependencies: any) { - // eslint-disable-next-line react-hooks/exhaustive-deps - return useEffect(callback, useDeepCompareMemoize(dependencies)); -} - export const useFiles: UseFiles = (props) => { const originalStateFromProps = getSandpackStateFromProps(props); diff --git a/yarn.lock b/yarn.lock index 169defc90..ee0d44a2d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8234,7 +8234,7 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -dequal@^2.0.0: +dequal@^2.0.0, dequal@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== @@ -18796,6 +18796,14 @@ use-clipboard-copy@^0.2.0: dependencies: clipboard-copy "^3.0.0" +use-deep-compare-effect@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/use-deep-compare-effect/-/use-deep-compare-effect-1.8.1.tgz#ef0ce3b3271edb801da1ec23bf0754ef4189d0c6" + integrity sha512-kbeNVZ9Zkc0RFGpfMN3MNfaKNvcLNyxOAAd9O4CBZ+kCBXXscn9s/4I+8ytUER4RDpEYs5+O6Rs4PqiZ+rHr5Q== + dependencies: + "@babel/runtime" "^7.12.5" + dequal "^2.0.2" + use-sync-external-store@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" From 13812eb3cb752487ae99d86359d1a68b5c3f93a8 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 16:16:42 +0000 Subject: [PATCH 25/26] Update package.json and useAppState.ts --- sandpack-client/package.json | 3 +-- sandpack-react/src/contexts/utils/useAppState.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sandpack-client/package.json b/sandpack-client/package.json index 6cc10e37d..b22535c14 100644 --- a/sandpack-client/package.json +++ b/sandpack-client/package.json @@ -47,11 +47,10 @@ ], "dependencies": { "@codesandbox/nodebox": "0.1.0", - "lodash.isequal": "^4.5.0", + "dequal": "^2.0.2", "outvariant": "1.3.0" }, "devDependencies": { - "@types/lodash.isequal": "^4.5.2", "@types/node": "^9.3.0", "console-feed": "3.3.0", "del": "^6.0.0", diff --git a/sandpack-react/src/contexts/utils/useAppState.ts b/sandpack-react/src/contexts/utils/useAppState.ts index 7d171764b..edba3dec8 100644 --- a/sandpack-react/src/contexts/utils/useAppState.ts +++ b/sandpack-react/src/contexts/utils/useAppState.ts @@ -1,5 +1,5 @@ import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client"; -import isEqual from "lodash.isequal"; +import { dequal as deepEqual } from "dequal"; import { useState } from "react"; import type { SandpackProviderProps } from "../.."; @@ -20,7 +20,7 @@ export const useAppState: UseAppState = (props, files) => { }); const originalStateFromProps = getSandpackStateFromProps(props); - const editorState = isEqual(originalStateFromProps.files, files) + const editorState = deepEqual(originalStateFromProps.files, files) ? "pristine" : "dirty"; From 0ced177264ee6ef1d327260bd6d7e55daea9b109 Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 24 Feb 2023 16:18:38 +0000 Subject: [PATCH 26/26] Update 5 files --- sandpack-client/src/clients/base.ts | 4 ++-- sandpack-client/src/clients/runtime/index.ts | 4 ++-- sandpack-react/package.json | 3 +-- sandpack-react/src/contexts/utils/useFiles.ts | 10 ++-------- yarn.lock | 17 ----------------- 5 files changed, 7 insertions(+), 31 deletions(-) diff --git a/sandpack-client/src/clients/base.ts b/sandpack-client/src/clients/base.ts index 3ab17316a..366bd8c72 100644 --- a/sandpack-client/src/clients/base.ts +++ b/sandpack-client/src/clients/base.ts @@ -1,4 +1,4 @@ -import isEqual from "lodash.isequal"; +import { dequal as deepEqual } from "dequal"; import type { ClientOptions, @@ -35,7 +35,7 @@ export class SandpackClient { * Clients handles */ public updateOptions(options: ClientOptions): void { - if (!isEqual(this.options, options)) { + if (!deepEqual(this.options, options)) { this.options = options; this.updateSandbox(); } diff --git a/sandpack-client/src/clients/runtime/index.ts b/sandpack-client/src/clients/runtime/index.ts index bd4154ec5..44365ad7e 100644 --- a/sandpack-client/src/clients/runtime/index.ts +++ b/sandpack-client/src/clients/runtime/index.ts @@ -1,4 +1,4 @@ -import isEqual from "lodash.isequal"; +import { dequal as deepEqual } from "dequal"; import type { SandpackMessage } from "../.."; import { nullthrows } from "../.."; @@ -163,7 +163,7 @@ export class SandpackRuntime extends SandpackClient { } updateOptions(options: ClientOptions): void { - if (!isEqual(this.options, options)) { + if (!deepEqual(this.options, options)) { this.options = options; this.updateSandbox(); } diff --git a/sandpack-react/package.json b/sandpack-react/package.json index cc2e1f533..3650886ff 100644 --- a/sandpack-react/package.json +++ b/sandpack-react/package.json @@ -52,7 +52,7 @@ "ansi-to-react": "6.1.6", "clean-set": "^1.1.2", "codesandbox-import-util-types": "^2.2.3", - "lodash.isequal": "^4.5.0", + "dequal": "^2.0.2", "lz-string": "^1.4.4", "react-devtools-inline": "4.4.0", "react-is": "^17.0.2" @@ -67,7 +67,6 @@ "@testing-library/react-hooks": "8.0.1", "@types/fs-extra": "^5.0.4", "@types/glob": "^5.0.35", - "@types/lodash.isequal": "^4.5.2", "@types/lz-string": "^1.3.34", "@types/node": "^9.4.6", "@types/react": "^18.0.15", diff --git a/sandpack-react/src/contexts/utils/useFiles.ts b/sandpack-react/src/contexts/utils/useFiles.ts index ef8c8659b..f5a6fd530 100644 --- a/sandpack-react/src/contexts/utils/useFiles.ts +++ b/sandpack-react/src/contexts/utils/useFiles.ts @@ -110,10 +110,7 @@ export const useFiles: UseFiles = (props) => { })); }, resetAllFiles: (): void => { - setState((prev) => ({ - ...prev, - files: originalStateFromProps.files, - })); + setState((prev) => ({ ...prev, files: originalStateFromProps.files })); }, setActiveFile: (activeFile: string): void => { if (state.files[activeFile]) { @@ -182,10 +179,7 @@ export const useFiles: UseFiles = (props) => { }; return [ - { - ...state, - visibleFilesFromProps: originalStateFromProps.visibleFiles, - }, + { ...state, visibleFilesFromProps: originalStateFromProps.visibleFiles }, operations, ]; }; diff --git a/yarn.lock b/yarn.lock index ee0d44a2d..5f19e3257 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5016,18 +5016,6 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash.isequal@^4.5.2": - version "4.5.6" - resolved "https://registry.yarnpkg.com/@types/lodash.isequal/-/lodash.isequal-4.5.6.tgz#ff42a1b8e20caa59a97e446a77dc57db923bc02b" - integrity sha512-Ww4UGSe3DmtvLLJm2F16hDwEQSv7U0Rr8SujLUA2wHI2D2dm8kPu6Et+/y303LfjTIwSBKXB/YTUcAKpem/XEg== - dependencies: - "@types/lodash" "*" - -"@types/lodash@*": - version "4.14.182" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" - integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== - "@types/lodash@^4.14.167": version "4.14.186" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.186.tgz#862e5514dd7bd66ada6c70ee5fce844b06c8ee97" @@ -12845,11 +12833,6 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"