diff --git a/package.json b/package.json index 3179d5d..e2e566f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "modal", "useModal" ], - "version": "0.1.7", + "version": "0.1.8", "main": "lib/index", "types": "lib", "files": [ diff --git a/src/Modal.tsx b/src/Modal.tsx index 581802c..662883c 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -1,4 +1,10 @@ -import React, { createContext, useCallback, useMemo, useState } from 'react'; +import React, { + createContext, + useCallback, + useMemo, + useRef, + useState, +} from 'react'; import { StyleSheet } from 'react-native'; import ModalComponent, { ModalProps } from 'react-native-modal'; @@ -8,11 +14,6 @@ const styles = StyleSheet.create({ }, }); -export interface Modal { - content: React.ReactNode; - options?: Partial; -} - export interface ModalProviderProps { children: React.ReactNode; modalProps?: Partial; @@ -31,19 +32,19 @@ export const ModalProvider: React.FC = ({ children, modalProps, }: ModalProviderProps) => { - const [modal, setModal] = useState(null); + const [content, setContent] = useState(null); + const optionsRef = useRef>({}); + const showModal = useCallback( (content: React.ReactNode, options?: Partial) => { - setModal({ - content, - options, - }); + setContent(content); + optionsRef.current = options; }, [], ); const closeModal = useCallback(() => { - setModal(null); + setContent(null); }, []); const value = useMemo(() => ({ showModal, closeModal }), [ @@ -56,15 +57,15 @@ export const ModalProvider: React.FC = ({ {children} - {modal?.content} + {content} ); diff --git a/tests/Modal.spec.tsx b/tests/Modal.spec.tsx index 8d22b7e..1eff1f9 100644 --- a/tests/Modal.spec.tsx +++ b/tests/Modal.spec.tsx @@ -1,7 +1,8 @@ import React, { useContext, useEffect } from 'react'; -import { Text } from 'react-native'; +import { Text, TouchableOpacity, View } from 'react-native'; import { create, act } from 'react-test-renderer'; import { ModalContext, ModalProvider } from '../src/Modal'; +import { waitForPaint } from './testhelper'; jest.useFakeTimers(); @@ -57,6 +58,72 @@ describe('Modal Provider', () => { expect(wrapper.root.findByType(Text).props.children).toBe('Hello World'); }); + test('showModal with options', async () => { + const onModalHideMock = jest.fn(); + const TestConsumer: React.FC = () => { + const { showModal, closeModal } = useContext(ModalContext); + const onShowModal = () => { + showModal(Hello World, { + onModalHide: onModalHideMock, + }); + }; + + const onCloseModal = () => { + closeModal(); + }; + return ( + + + Show Modal + + + + Close Modal + + + ); + }; + + const wrapper = create( + + + , + ); + await waitForPaint(); + + const { onPress: onShowModal } = wrapper.root.findByProps({ + testID: 'show-modal', + })?.props; + act(() => { + onShowModal(); + }); + + await waitForPaint(); + + expect( + wrapper.root.findAllByProps({ + testID: 'modal-content', + }), + ).toHaveLength(2); + + const { onPress: onCloseModal } = wrapper.root.findByProps({ + testID: 'close-modal', + })?.props; + act(() => { + onCloseModal(); + }); + + await waitForPaint(); + + expect( + wrapper.root.findAllByProps({ + testID: 'modal-content', + }), + ).toHaveLength(0); + + expect(onModalHideMock).toHaveBeenCalled(); + }); + test('closeModal', () => { const TestConsumer: React.FC = () => { const { showModal, closeModal } = useContext(ModalContext); diff --git a/tests/testhelper.ts b/tests/testhelper.ts new file mode 100644 index 0000000..4282cd9 --- /dev/null +++ b/tests/testhelper.ts @@ -0,0 +1,6 @@ +export async function waitForPaint(times = 1): Promise { + for (let i = 0; i < times + 1; i++) { + jest.advanceTimersByTime(1000); + await Promise.resolve(); + } +}