Skip to content

fix: memoize compiled component in Preview to preserve state across re-renders - #92

Merged
JeremyRH merged 1 commit into
mainfrom
copilot/fix-preview-recompile-issue
Jun 30, 2026
Merged

JeremyRH merged 1 commit into
mainfrom
copilot/fix-preview-recompile-issue

Conversation

Copilot AI commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Preview called evalModule(code, availableImports) directly in the render body. evalModule runs Babel transform + new Function(...) on every call, so DefaultExport was a fresh function reference on every render. React keys component instances by type identity, causing an unmount/remount — and full state reset — on any re-render that didn't originate from a code edit (e.g. args/controls change, globals update via a decorator).

Changes

  • src/Preview.tsx — wrap evalModule in React.useMemo([code]). availableImports is intentionally excluded from deps: callers spread a fresh object on every render ({ react: React, ...state.availableImports }), so including it would bust the memo every render. Error handling is moved inside the memo, returning an error-rendering component function so it's compatible with the memoization path.
// Before: new function type every render → remount → state reset
DefaultExport = code ? evalModule(code, availableImports).default : undefined;

// After: stable reference, only recompiles when code changes
const DefaultExport = React.useMemo<React.ComponentType<any>>(() => {
  try {
    const exp = code ? evalModule(code, availableImports).default : undefined;
    // ...validate...
    return exp;
  } catch (error) {
    return () => <pre style={errorStyle}>{String(error)}</pre>;
  }
}, [code]); // intentionally omits availableImports — see block comment

Side effect: Babel transform no longer runs on every render, only on actual code changes.

  • src/index.test.tsx — two new tests:
    • state is preserved when componentProps change but code is unchanged
    • state is reset when code changes (correct remount behavior validated)

Copilot AI changed the title [WIP] Fix preview recompilation on every render fix: memoize compiled component in Preview to preserve state across re-renders Jun 29, 2026
Copilot AI requested a review from JeremyRH June 29, 2026 21:38

This comment was marked as duplicate.

@JeremyRH
JeremyRH marked this pull request as ready for review June 29, 2026 23:38
Copilot AI requested a review from JeremyRH June 29, 2026 23:43
Copilot AI requested a review from JeremyRH June 29, 2026 23:47
Repository owner deleted a comment from Copilot AI Jun 30, 2026
Repository owner deleted a comment from Copilot AI Jun 30, 2026
@JeremyRH
JeremyRH force-pushed the copilot/fix-preview-recompile-issue branch from 7e7edb5 to 5d8983b Compare June 30, 2026 01:28
@JeremyRH
JeremyRH merged commit b536c7b into main Jun 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants