Skip to content

Commit

Permalink
Fix missing param in modalfy().closeModal() 🐞
Browse files Browse the repository at this point in the history
  • Loading branch information
CharlesMangwa committed Sep 26, 2020
1 parent c1a55ff commit eb1b526
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 19 deletions.
41 changes: 34 additions & 7 deletions lib/ModalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,39 @@ const createModalState = (): ModalStateType<any> => {
return stackItem?.params?.[paramName] || defaultValue
}

const closeModal = <P>(stackItem?: ModalStackItem<P>) => {
const closeModal = <P>(
closingElement?: Exclude<keyof P, symbol> | ModalStackItem<P>,
) => {
const {
stack: { openedItems },
stack: { openedItems, names },
} = state

if (stackItem && openedItems.has(stackItem)) {
openedItems.delete(stackItem)
if (typeof closingElement === 'string') {
invariant(
names.some((name) => name === closingElement),
`'${closingElement}' is not a valid modal name. Did you mean any of these: ${names.map(
(validName) => `\n• ${String(validName)}`,
)}`,
)

let wasItemRemoved = false
let reversedOpenedItemsArray = Array.from(openedItems).reverse()

reversedOpenedItemsArray.forEach((openedItem) => {
if (openedItem.name === closingElement && !wasItemRemoved) {
openedItems.delete(openedItem)
wasItemRemoved = true
}
})

if (!wasItemRemoved) {
console.warn(`There was no opened ${closingElement} modal.`)
}
} else if (
closingElement &&
openedItems.has(closingElement as ModalStackItem<P>)
) {
openedItems.delete(closingElement as ModalStackItem<P>)
} else {
const staleStackItem = Array.from(openedItems).pop()
if (staleStackItem) openedItems.delete(staleStackItem)
Expand Down Expand Up @@ -267,13 +293,14 @@ export const modalfy = <
/**
* This function closes the currently displayed modal by default.
*
* You can also provide a `modalName` if you want to close
* a different modal than the latest opened.
* You can also provide a `modalName` if you want to close a different modal
* than the latest opened. This will only close the latest instance of that modal,
* see `closeModals()` if you want to close all instances.
*
* @example modalfy().closeModal()
* @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modalprop#closemodal
*/
closeModal: () => ModalState.closeModal(),
closeModal: (modalName: M) => ModalState.closeModal(modalName),
/**
* This function closes all the instances of a given modal.
*
Expand Down
23 changes: 14 additions & 9 deletions lib/StackItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useEffect, useRef, memo } from 'react'
import { Animated, StyleSheet } from 'react-native'
import {
useMemoOne as useMemo,
Expand Down Expand Up @@ -51,7 +51,7 @@ const StackItem = <P extends ModalfyParams>({
[],
)

const animatedListenerId = React.useRef<string | undefined>()
const animatedListenerId = useRef<string | undefined>()

const {
position: verticalPosition,
Expand All @@ -66,7 +66,7 @@ const StackItem = <P extends ModalfyParams>({
animationIn,
} = useMemo(() => getStackItemOptions(stackItem, stack), [stack, stackItem])

React.useEffect(() => {
useEffect(() => {
let handleAnimatedListener: ModalEventCallback = () => undefined

if (transitionOptions && typeof transitionOptions !== 'function') {
Expand Down Expand Up @@ -146,9 +146,14 @@ const StackItem = <P extends ModalfyParams>({
],
)

const closeStackItem = useCallback(() => {
updateAnimatedValue(position - 1, closeModal)
}, [closeModal, position, updateAnimatedValue])
const closeStackItem = useCallback(
(closingElement) => {
if (closingElement === currentModal) {
updateAnimatedValue(position - 1, () => closeModal(closingElement))
} else closeModal(closingElement)
},
[closeModal, currentModal, position, updateAnimatedValue],
)

const closeAllStackItems = useCallback(() => {
updateAnimatedValue(position - 1, closeAllModals)
Expand Down Expand Up @@ -240,11 +245,11 @@ const StackItem = <P extends ModalfyParams>({
}
}, [verticalPosition])

React.useEffect(() => {
useEffect(() => {
updateAnimatedValue(position)
if (wasClosedByBackdropPress) {
if (backBehavior === 'clear') closeAllStackItems()
else closeStackItem()
else closeStackItem(undefined)
}
}, [
backBehavior,
Expand Down Expand Up @@ -272,7 +277,7 @@ const styles = StyleSheet.create({
},
})

export default React.memo(
export default memo(
StackItem,
(prevProps, nextProps) =>
prevProps.position === nextProps.position &&
Expand Down
5 changes: 3 additions & 2 deletions lib/useModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ export default function <P extends ModalfyParams>(): UsableModalProp<P> {
/**
* This function closes the currently displayed modal by default.
*
* You can also provide a `modalName` if you want to close
* a different modal than the latest opened.
* You can also provide a `modalName` if you want to close a different modal
* than the latest opened. This will only close the latest instance of that modal,
* see `closeModals()` if you want to close all instances.
*
* @example modal.closeModal()
* @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modalprop#closemodal
Expand Down
2 changes: 1 addition & 1 deletion types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export interface ModalContextProvider<
> {
currentModal: M | null
closeAllModals: () => void
closeModal: (stackItem?: ModalStackItem<P>) => void
closeModal: (stackItem?: M | ModalStackItem<P>) => void
closeModals: (modalName: M) => boolean
getParam: <N extends keyof P[M], D extends P[M][N]>(
hash: ModalStackItem<P>['hash'],
Expand Down

0 comments on commit eb1b526

Please sign in to comment.