import * as React from 'react';

const useIsFirstRender = (): boolean => {
  const isFirst = React.useRef(true);

  if (isFirst.current) {
    isFirst.current = false;

    return true;
  } else {
    return false;
  }
};

/**
 * Use case:
 * - A component must be rendered on the server.
 * - On the client-side, rendering is conditional e.g. based on window width.
 * - However, in order for hydration to succeed, the first client render must
 *   match the DOM generated from the HTML returned by the server. This means
 *   the component must be rendered again during the first client render and
 *   removed afterwards.
 * - Hydration is expensive, so we really don't want to pay that penalty only
 *   for the element to be removed immediately afterwards.
 *
 * This component conditionally skips hydrating children by removing them from
 * the DOM _before the first client render_. Removing them before ensures
 * hydration is successful.
 */
export const SkipRenderOnClient: React.FC<{
  children: React.ReactNode;
  shouldRenderOnClient: IO<boolean>;
}> = ({ children, shouldRenderOnClient }) => {
  const id = React.useId();
  const isBrowser = typeof window !== 'undefined';
  const isFirstRender = useIsFirstRender();

  if (isBrowser && isFirstRender && shouldRenderOnClient() === false) {
    const el = document.getElementById(id);
    if (el !== null) {
      el.innerHTML = '';
    }
  }

  const shouldRender = isBrowser ? shouldRenderOnClient() : true;

  return <div id={id}>{shouldRender && children}</div>;
};
