NativeBase
NativeBase copied to clipboard
[Bug] Toast is not working within a Modal
react-native, react and native-base version
RN: 0.45.1 React:16.0.0-alpha.12 native-base: 2.1.5
Expected behaviour
Toast to be shown in react native Modal
Actual behaviour
The toast is not shown in react native Modal
Steps to reproduce (code snippet or screenshot)
Do Toast.show() in a Modal
Is the bug present in both ios and android or in any one of them?
No that I know of. This was working with RN on 0.44 and native-base on a lower version (I can't remember exactly which one, either 2.1.4 or 2.1.3)
@JLLLinn Check the latest of NativeBase i.e, v2.2.0
Was this verified that it was fixed? I think I'm experiencing it as well. My issue is that the Modal is covering the Toast so it isn't visible.
I'm on RN 0.46.4 and native base 2.2.1 and using the ios emulator.
Thanks!
Same problem. I'm on RN 0.46.1 and native base 2.2.1 and using the ios emulator.
Exactly the same problem using RN 0.47 and NativeBase 2.2.1. Any news about it? thanks!
The Toast still appears behind the Modal (from React Native):
the code is basically this:
import React from 'react';
import {
Modal,
Toast,
Text,
View,
} from 'react-native';
export default class LoginScreen extends React.Component<Props, State> {
state = {
modalVisible: false,
}
onResetPassword() {
Toast.show({
text: message,
duration: 2000,
position: "top",
textStyle: { textAlign: "center" },
});
}
render() {
return (
<View>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
>
<View>...</View>
</Modal>
</View>
)
}
}
Any suggestions?
I see there's something called zIndex as Layout Props - React Native
Using:
$ yarn list --depth=0 | grep 'native-base@\| react-native@'
├─ [email protected]
├─ [email protected]
Can something be done to the ToastContainer.js? https://github.com/GeekyAnts/NativeBase/blob/master/src/basic/ToastContainer.js
@gianpaj Looks like you are using React-Native-Seed boilerplate. Nice! We will check this issue
I just want to add that I’m having this issue too with v 2.3.3
FYI: this issue happens both on Android and iOS
Still present on 2.3.5
I think I'm just going to use the Toast
from ant-design-mobile.
My bad. Ant-Design Toast doesn't work. It also appears under the react-native Modal
@gianpaj I'm also using antd-mobile for the datepicker. Perhaps I should take a look at their toast implementation too.
@gianpaj What was the purpose of sharing graphs for commit-activity?
Any hotfix for now with v2.3.10 ?
Any chance this will be fixed anytime soon?
Сталкивался с этой проблемой недавно, решил следующим способом. Просто добавляем в Modal элемент Root, а в него весь контент который вам нужен
P.S. на английский переводить лень, главное ведь код
translation : Faced this problem recently, I decided in the following way. Just add the Root element to the Modal, and all the content you need is in it
import { Root, Container, Content } from 'native-base';
<Modal>
<Root>
<Container>
<Content>
// .. modal content with toast
</Content>
</Container>
</Root>
</Modal>
@Zeratyll Hey! It doesn't work for me at all, the toast still appears behind the Modal.
@doreentseng Tried @Zeratyll 's solution of putting <Root/>
into <Modal/>
, but it still didn't work.
@gianpaj Also tried to put style : { zIndex: 1000 }
into Toast.show()
, no effect as well.
All of the results are tested in a real iPad.
Tried Modal component from both original react-native and react-native-community, both of them didn't work. Will native-base provide its own modal component?
@SupriyaKalghatgi @shivrajkumar Dear collaborators, when can we get an fix?
checked this issue after merging PR https://github.com/GeekyAnts/NativeBase/pull/1700. Placing Root inside a modal component as suggested by @Zeratyll https://github.com/GeekyAnts/NativeBase/issues/985#issuecomment-383596951 is working after merging. See attached Gif.
Sample code
import React from 'react';
import { Modal } from "react-native";
import { createStackNavigator } from 'react-navigation';
import { Root, Container, Text, Header, Left, Body, Right, Title, Content, Button, Toast } from 'native-base';
class HomeScreen extends React.Component {
state = { modalVisible: false }
render() {
return (
<Container>
<Header>
<Left />
<Body>
<Title>Home screen</Title>
</Body>
<Right />
</Header>
<Content>
<Button onPress={() => this.setState({ modalVisible: !this.state.modalVisible })} style={{ margin: 20 }}>
<Text>Show modal</Text>
</Button>
</Content>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}>
<Root>
<Container style={{ padding: 20 }}>
<Button style={{ margin: 20 }} onPress={() => Toast.show({
text: 'Wrong password!',
buttonText: 'Okay'
})}>
<Text>Show toast</Text>
</Button>
<Button style={{ margin: 20 }} onPress={() => this.setState({ modalVisible: !this.state.modalVisible })}>
<Text>Hide modal</Text>
</Button>
</Container>
</Root>
</Modal>
</Container>
);
}
}
const App = createStackNavigator({
Home: {
screen: HomeScreen
},
}, {
navigationOptions: {
header: null
}
});
export default () => <Root>
<App />
</Root>
Gif
Edit : As @gianpaj pointed out this may not be a viable option. Please see the below comment.
Placing Root inside a modal component as suggested ... is working fine @akhil-geekyants
This is not ideal or neither practical.
The state of Modal(s) should not be at the Root of an application. It should be where the Modal needs to appear, i.e. inside a screen/component/container.
If we had to do the way you suggest, the state of the Modal needs to pass down all the way to the Component in need (via props or in order ways).
I have to say this is not a viable option for any decent size application.
I don't know at the moment how to solve this, but pretty sure that's not it. Happy to be corrected if I'm wrong.
@gianpaj updated my comment.
Also having this problem. The Root workaround does work but also has an unwanted side-effect that windowed (non-fullscreen) modals no longer appear vertically centered, and no JSX adjustments appear to help.
The above Root fix didn't work for me as I'd like it to, as it completely ruins the vertical centring of the Toast
My workaround for modals.
scene.js
<Scene>
<ModalComponent />
</Scene>
ModalComponent.js
import Toast from 'mypathto/Toast';
class ModalComponent Component {
showToast() {
Toast.show({
text: 'modal toast',
position: 'bottom',
duration: 3000
});
}
render() {
return (
<Modal>
<View>
<Button onPress={()=>this.showToast()}><Text>Toast<Text></Button>
<Toast
ref={c => {
if (c) Toast.toastInstance = c;
}}
/>
</View>
</Modal>
)
}
}
mypathto/Toast.js
import {
Toast as ToastNB,
} from "native-base";
class Toast extends ToastNB {
}
export default Toast;
Сталкивался с этой проблемой недавно, решил следующим способом. Просто добавляем в Modal элемент Root, а в него весь контент который вам нужен
P.S. на английский переводить лень, главное ведь код
translation : Faced this problem recently, I decided in the following way. Just add the Root element to the Modal, and all the content you need is in it
import { Root, Container, Content } from 'native-base'; <Modal> <Root> <Container> <Content> // .. modal content with toast </Content> </Container> </Root> </Modal>
Very good, it works with me
My workaround for modals.
scene.js
<Scene> <ModalComponent /> </Scene>
ModalComponent.js
import Toast from 'mypathto/Toast'; class ModalComponent Component { showToast() { Toast.show({ text: 'modal toast', position: 'bottom', duration: 3000 }); } render() { return ( <Modal> <View> <Button onPress={()=>this.showToast()}><Text>Toast<Text></Button> <Toast ref={c => { if (c) Toast.toastInstance = c; }} /> </View> </Modal> ) } }
mypathto/Toast.js
import { Toast as ToastNB, } from "native-base"; class Toast extends ToastNB { } export default Toast;
Works for me, Nice Solution
My workaround for modals.
scene.js
<Scene> <ModalComponent /> </Scene>
ModalComponent.js
import Toast from 'mypathto/Toast'; class ModalComponent Component { showToast() { Toast.show({ text: 'modal toast', position: 'bottom', duration: 3000 }); } render() { return ( <Modal> <View> <Button onPress={()=>this.showToast()}><Text>Toast<Text></Button> <Toast ref={c => { if (c) Toast.toastInstance = c; }} /> </View> </Modal> ) } }
mypathto/Toast.js
import { Toast as ToastNB, } from "native-base"; class Toast extends ToastNB { } export default Toast;
It's necessary to extend the Toast? I tried the trick directly with NB export and it worked.
EDIT: Yes, it's necessary beacuse the ref to the root is the same for all present and future Toasts (Without extending the Toast, it will try to render within the modal even if it doesn't exist anymore).
onPress={()=>this.setState({ toastVisible: !this.state.toastVisible },() =>Toast.show({ text: 'Wrong password!', buttonText: 'Okay' }))}
This code is working for me. Thanks @akhil-geekyants. This comment helped me https://github.com/GeekyAnts/NativeBase/issues/985#issuecomment-398688935
As mentioned in NB Docs https://docs.nativebase.io/Components.html#toast-def-headref - For Toast to work, you need to wrap your topmost component inside <Root> from native-base.
,the solution is to wrap Toast
with Root
within Modal
, which has already been found in discussion above...
Wrapping Modal content with Root solved the problem with z-indexing Toast, but this problem appears next https://github.com/GeekyAnts/NativeBase/issues/937
In my case I use Modal
as component and the Toast
is being shown after executing an async function, this works for me:
Toast:
import { Toast as ToastNB } from "native-base";
class Toast extends ToastNB {
}
export default Toast;
Modal Component:
import Toast from 'path/toast';
const ModalContainer = ({
visible, onClose, children, onShow,
}) => (
<Modal
visible={visible}
onRequestClose={onClose}
onShow={() => onShow(Toast)}
>
<View>
{children}
</View>
<Toast
ref={(t) => {
Toast.toastInstance = t;
}}
/>
</Modal>
);
Usign the Modal Component:
import ModalContainer from 'path/modalContainer/;
class SomeClass Component {
showToast() {
add1(10).then(() => this.toastInstance.show({
text: 'modal toast',
position: 'bottom',
duration: 3000
}));
}
render() {
return (
<ModalContainer onShow={(e) => { this.toastInstance = e; }}>
<Text>Hi</Text>
</ModalContainer>
)
}
}