diff --git a/src/App.tsx b/src/App.tsx index 00bea60..2ddeef2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -19,7 +19,6 @@ import { getWebR, onRestart } from './r/webrClient'; import './App.css'; export default function App() { - const [restarts, setRestarts] = useState(0); // Spec 3.5: webR starts in the background on first app load, not when the // first lesson opens. Mounted here rather than in main.tsx so it is testable // by rendering App. Both calls are memoised, so StrictMode's double mount and @@ -29,12 +28,9 @@ export default function App() { // status that RStatus renders. This only stops an unhandled rejection. const boot = () => void getWebR().then((r) => prepareSession(r, fetchDataset)).catch(() => {}); boot(); - // After "Restart R": remount the page, so every lesson environment, code - // block and console that held the old R starts over on the new one. - return onRestart(() => { - setRestarts((count) => count + 1); - boot(); - }); + // After "Restart R" boot the new R in the background. The page stays put: + // useLessonSession gives it a fresh environment on the new R. + return onRestart(boot); }, []); useEffect(() => { @@ -116,7 +112,7 @@ export default function App() {
- + } /> } /> } /> diff --git a/src/r/useLessonSession.ts b/src/r/useLessonSession.ts index f25f6d9..b773c3e 100644 --- a/src/r/useLessonSession.ts +++ b/src/r/useLessonSession.ts @@ -3,7 +3,7 @@ import type { RObject, WebR } from 'webr'; import { createLessonEnv, destroyEnv } from './environments'; import { ensurePackages, fetchDataset, prepareSession } from './session'; import { restoreUploads } from './uploads'; -import { getWebR, setStatus } from './webrClient'; +import { getWebR, onRestart, setStatus } from './webrClient'; /** What the hook needs from a lesson: its identity, and what it must attach. */ export type SessionLesson = { id: string; packages?: string[] }; @@ -25,6 +25,10 @@ export function useLessonSession( const packages = lesson?.packages; const [webR, setWebR] = useState(null); const [env, setEnv] = useState(null); + // "Restart R" replaces the R instance. Counting restarts reruns the effect + // below on the new R, so the page and the code typed into it stay put. + const [restarts, setRestarts] = useState(0); + useEffect(() => onRestart(() => setRestarts((count) => count + 1)), []); useEffect(() => { if (key === null) return; @@ -66,7 +70,7 @@ export function useLessonSession( // After a restart the old R is gone along with its environments. if (created && createdBy) destroyEnv(createdBy, created).catch(() => {}); }; - }, [key]); + }, [key, restarts]); return { webR, env }; }