caiiiycuk / js-dos

The best API for running dos programs in browser
https://js-dos.com
1.03k stars 130 forks source link

PSA: Vite bundler HMR re-render bug #287

Closed hughdtt closed 3 months ago

hughdtt commented 1 year ago

PSA for those following the React bootstrap instructions on site documentation

Issue: Vite's hot module reloader doesn't clean up React DosPlayer component properly

Context:

image

Fix:

Typescript component ends up looking a little like this:

import React, { useEffect, useRef, useState } from "react";
import { DosPlayer as Instance, DosPlayerFactoryType } from "js-dos";

declare const Dos: DosPlayerFactoryType;

interface PlayerProps {
    bundleUrl: string;
}

export default function DosPlayer(props: PlayerProps) {
    const rootRef = useRef<HTMLDivElement>(null);
    const [dos, setDos] = useState<Instance | null>(null);

    useEffect(() => {
        if (rootRef.current === null) {
            return;
        }

        const root = rootRef.current as HTMLDivElement;
        const instance = Dos(root);
        setDos(instance);

        return () => {
            instance.stop();
            root.innerHTML = ''; //fix
        };
    }, [rootRef]);

    useEffect(() => {
        if (dos !== null) {
            dos.run(props.bundleUrl); // ci is returned
        }
    }, [dos, props.bundleUrl]);

    return <div ref={rootRef} style={{ width: "100%", height: "100%" }}></div>;
}

End of the day, it's not a js-dos issue but a weird interaction with Vite.

Just thought it might be helpful for people who run into the same issue. It gave me a headache far longer than it should have 🤣

Good day

caiiiycuk commented 1 year ago

Wow. Thank you very much, I think we need to add this to docs. Cleaning the DOM tree is good idea in any case.