projects/deliberation_at_scale/packages/frontend/components/LocalMedia/conditional.tsx (30 lines of code) (raw):
'use client';
import { PermissionState } from '@/state/slices/room';
import { useAppSelector } from '@/state/store';
import dynamic from 'next/dynamic';
import { PropsWithChildren, createContext, useContext } from 'react';
// FFS: https://github.com/vercel/next.js/issues/7906
// We need to create a context to keep the children mounted while the dynamic
// component mounts. If we don't the children get dismounted, and re-mounted,
// effects get triggered and everything gets progressively worse.
const LoadingValueContext = createContext<JSX.Element | null>(null);
// A simple loader retrieves the children and shows those
function Loader() {
const children = useContext(LoadingValueContext);
return children || null;
}
const DynamicLocalMediaProvider = dynamic(
() => import('./provider'),
{ ssr: false, loading: Loader },
);
/**
* A provider that will conditionally mount `LocalMediaProvider` in the
* application tree based on whether permissions have been requested through
* setting `permission` in the Redux store.
*/
export default function ConditionalLocalMediaProvider({ children }: PropsWithChildren) {
const permission = useAppSelector((state) => state.room.permission);
if (permission === PermissionState.REQUESTED) {
return (
<LoadingValueContext.Provider value={children as JSX.Element}>
<DynamicLocalMediaProvider>
{children}
</DynamicLocalMediaProvider>
</LoadingValueContext.Provider>
);
} else if (permission === PermissionState.NONE) {
return children;
} else {
return null;
}
}