feat: render iframe with xblocks (#1375)
This refactors the CourseUnit component by removing the DraggableList and CourseXBlock components and replacing them with a simpler XBlockContainerIframe. Additionally, it introduces new constants for iframe handling.
This commit is contained in:
2
src/generic/hooks/index.tsx
Normal file
2
src/generic/hooks/index.tsx
Normal file
@@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export { useEventListener } from './useEventListener';
|
||||
62
src/generic/hooks/tests/useEventListener.test.tsx
Normal file
62
src/generic/hooks/tests/useEventListener.test.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
|
||||
import { useEventListener } from '../useEventListener';
|
||||
|
||||
describe('useEventListener', () => {
|
||||
let addEventListenerSpy: jest.SpyInstance;
|
||||
let removeEventListenerSpy: jest.SpyInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
addEventListenerSpy = jest.spyOn(global, 'addEventListener');
|
||||
removeEventListenerSpy = jest.spyOn(global, 'removeEventListener');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should add event listener on mount', () => {
|
||||
const handler = jest.fn();
|
||||
renderHook(() => useEventListener('click', handler));
|
||||
|
||||
expect(addEventListenerSpy).toHaveBeenCalledWith('click', handler);
|
||||
});
|
||||
|
||||
it('should remove event listener on unmount', () => {
|
||||
const handler = jest.fn();
|
||||
const { unmount } = renderHook(() => useEventListener('click', handler));
|
||||
|
||||
unmount();
|
||||
|
||||
expect(removeEventListenerSpy).toHaveBeenCalledWith('click', handler);
|
||||
});
|
||||
|
||||
it('should update event listener when handler changes', () => {
|
||||
const handler1 = jest.fn();
|
||||
const handler2 = jest.fn();
|
||||
const { rerender } = renderHook(({ handler }: {
|
||||
handler: (event: Event) => void
|
||||
}) => useEventListener('click', handler), {
|
||||
initialProps: { handler: handler1 },
|
||||
});
|
||||
|
||||
rerender({ handler: handler2 });
|
||||
|
||||
expect(removeEventListenerSpy).toHaveBeenCalledWith('click', handler1);
|
||||
expect(addEventListenerSpy).toHaveBeenCalledWith('click', handler2);
|
||||
});
|
||||
|
||||
it('should update event listener when type changes', () => {
|
||||
const handler = jest.fn();
|
||||
const { rerender } = renderHook(({ type }: {
|
||||
type: keyof WindowEventMap
|
||||
}) => useEventListener(type, handler), {
|
||||
initialProps: { type: 'click' },
|
||||
});
|
||||
|
||||
rerender({ type: 'scroll' });
|
||||
|
||||
expect(removeEventListenerSpy).toHaveBeenCalledWith('click', handler);
|
||||
expect(addEventListenerSpy).toHaveBeenCalledWith('scroll', handler);
|
||||
});
|
||||
});
|
||||
27
src/generic/hooks/useEventListener.tsx
Normal file
27
src/generic/hooks/useEventListener.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { useEffect, useRef, MutableRefObject } from 'react';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function useEventListener<K extends keyof WindowEventMap>(
|
||||
type: K,
|
||||
handler: (event: WindowEventMap[K]) => void,
|
||||
) {
|
||||
// We use this ref so that we can hold a reference to the currently active event listener.
|
||||
const eventListenerRef = useRef<(event: WindowEventMap[K]) => void | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// If we currently have an event listener, remove it.
|
||||
if (eventListenerRef.current !== null) {
|
||||
global.removeEventListener(type, eventListenerRef.current);
|
||||
}
|
||||
// Now add our new handler as the event listener.
|
||||
global.addEventListener(type, handler);
|
||||
// And then save it to our ref for next time.
|
||||
(eventListenerRef as MutableRefObject<(event: WindowEventMap[K]) => void>).current = handler;
|
||||
// When the component finally unmounts, use the ref to remove the correct handler.
|
||||
return () => {
|
||||
if (eventListenerRef.current !== null) {
|
||||
global.removeEventListener(type, eventListenerRef.current);
|
||||
}
|
||||
};
|
||||
}, [type, handler]);
|
||||
}
|
||||
Reference in New Issue
Block a user