projects/deliberation_at_scale/packages/frontend/components/RoomConnection/conditional.tsx (31 lines of code) (raw):
'use client';
import { useExternalRoomId } from '@/hooks/useRoom';
import { PermissionState } from '@/state/slices/room';
import { useAppSelector } from '@/state/store';
import dynamic from 'next/dynamic';
import { usePathname } from 'next/navigation';
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 DynamicRoomConnectionProvider = dynamic(
() => import('./provider'),
{ ssr: false, loading: Loader }
);
/**
* This will conditionally inject the `RoomConnectionProvider` in the
* application tree based on whether a `roomId` has been set in Redux.
*/
export default function ConditionalRoomConnectionProvider({ children }: PropsWithChildren) {
const hasRequested = useAppSelector((state) => state.room.permission === PermissionState.REQUESTED);
const externalRoomId = useExternalRoomId();
// only show connection when really in the room
// otherwise it can still activate the camera when for example in the evaluation screen
const pathname = usePathname();
const isInRoom = pathname?.includes('/room');
return isInRoom && externalRoomId && hasRequested ? (
<LoadingValueContext.Provider value={children as JSX.Element}>
<DynamicRoomConnectionProvider>
{children}
</DynamicRoomConnectionProvider>
</LoadingValueContext.Provider>
) : (
children
);
}