I have created my own modal component based on react-native-modal with "controls" through useRef. This is my code.
import React, {useState, forwardRef, useImperativeHandle} from 'react';
import RNModal from 'react-native-modal';
// <Modal />
export default Modal = forwardRef(({children, ...props}, ref) => {
const [isVisible, setIsVisible] = useState(false);
useImperativeHandle(
ref,
() => ({
show: () => {
setIsVisible(true);
},
hide: () => {
setIsVisible(false);
},
}),
[],
);
const childrenWithProps = React.Children.map(children, child => {
return React.cloneElement(child, {isMounted: isVisible});
});
return (
<RNModal
isVisible={isVisible}
animationInTiming={200}
animationOutTiming={200}
iseNativeDriver={true}
hideModalContentWhileAnimating={true}
onBackdropPress={ref.current?.hide}
onBackButtonPress={ref.current?.hide}
{...props}>
{childrenWithProps}
</RNModal>
);
});
As you can see, I’m trying to pass the "isMounted" prop through React.cloneElement. This way, I can control useEffect functions to run whenever the modal opens or closes.
The problem is: this doesn’t work. When I have code like this, it doesn’t work.
const MyModal = forwardRef(({isMounted, ...props}, ref) => {
useEffect(() => {
console.log(isMounted);
}, [isMounted]);
return (
<Modal ref={ref}>
<View>...</View>
</Modal>
);
});
What is wrong with my code?
2
Answers
I suspect the
React.cloneElement
is working.Perhaps your refs setup is a little muddled?
Check this code – it may be what you intended:
A few points:
visible:false
cloneElement
workingonBackdropPress
, before it tried to call the imperative API, which is exposed for parents. Instead I just used the internal createdsetIsVisisble
state handlerThe issue with your code is that you’re passing the isMounted prop to the Modal component, but then you’re not passing it down to the actual modal content (childrenWithProps). Therefore, the MyModal component doesn’t receive the isMounted prop.
To fix this, you need to make sure that the isMounted prop is passed down to the child components inside the Modal. You can modify the useImperativeHandle block in your Modal component to achieve this:
Now, the isMounted prop should be passed down to the child components within the Modal. Ensure that your MyModal component is correctly using the isMounted prop:
With these changes, the useEffect inside MyModal should correctly log the isMounted prop when the modal is opened or closed.