Persisted progress bar

18 Views Asked by At

I'm developing a web compiler in TypeScript and I've encountered a small, but still irritating issue.

I have a progress bar inside an iframe element which keeps rendering for a short amount of time. I want that progress bar to be rendered only when there's a code bundling process.

Here's a piece of that TypeScript code:

codeCell.tsx (The CodeCell component):

const bundle = useTypedSelector((state) => state.bundles[cell.id]);
return (
  <>
    <Resizable direction="vertical">
      <div className="h-100 d-flex flex-row position-relative">
        <Resizable direction="horizontal">
          <div className="position-relative w-100">
            <CodeEditor
              initialValue={cell.content}
              onChange={handleEditorChange}
            />
          </div>
        </Resizable>
        <div className="progress-wrapper">
          {!bundle || bundle.loading ? (
            <div className="progress-cover">
              <progress hidden={!bundle} max="100"/>
            </div>
          ) : (
            <Preview code={bundle.code} err={bundle.err} cell={cell}/>
          )}
        </div>
      </div>
    </Resizable>
  </>
);

useTypedSelector.ts (useTypedSelector hook):

export const useTypedSelector: TypedUseSelectorHook<RootState> = (selector) => {
  const result = useSelector(selector, shallowEqual);
  return useMemo(() => result, [result]);
};

const shallowEqual = (a: any, b: any) => {
  if (a === undefined || b === undefined) {
    return false;
  }

  for (let key in a) {
    if(a[key] !== b[key]) {
      return false;
    }
  }

  for (let key in b) {
    if (!(key in a)) {
      return false;
    }
  }

  return true;
};

preview.tsx (Preview component):

interface PreviewProps {
  code: string;
  err: string;
  cell: Cell;
}

const Preview: React.FC<PreviewProps> = ({ code, err, cell }) => {
  const iframe = useRef<any>();

  useEffect(() => {
    iframe.current.srcdoc = html;
    setTimeout(() => {
      iframe.current.contentWindow.postMessage(code, '*'); // Posts the result from the code bundling
    }, 10);
  }, [code]);

  return (
    <div className="preview-wrapper">
      <iframe
      title="code preview"
      ref={iframe}
      sandbox="allow-scripts"
      srcDoc={html}/>
      {err && (
        <div className="preview-error">
          {err}
        </div>
      )}
      <div style={{ display: "none" }}>
        <div className="action-bar">
          <ActionBar id={cell.id}/>
        </div>
      </div>
    </div>
  );
}

export default Preview;

One of the approaches I tried is using a ternary operator inside the Preview component's props stating that if there's a code bundling process you'll see the progress bar (the same if there's a code error) and if not (there's no code at all), you'll see an empty string (meaning you'll see an empty iframe element).

0

There are 0 best solutions below