display a view above a react nativigation modal - react-native

I have a custom snackbar component which has a zIndex higher than other views and an absolute position in the app.
The snackbar works fine, as long as no modals are opened. The problem is, I have nested navigation with nested modals and the snackbar component needs to be on top, all the time.
currently, my screenOptions are: { presentation: 'modal' }
Others like containedModal work, but gives me stacked headers for all the parent modals. I like the way modal presentation looks on iOs. Any ideas how an absolute View can be displayed above any modal from the root of the app?

Z-index in RN doesn't work the same as it does on web - see the docs for more. Components are rendered as a tree, with the first items on the bottom and stacking until the last items are on top.
Therefore you can put a component on top of everything else by rendering it outside and after everything else. I.e.
// App.js
const App = () => {
return (
<>
<NavigationContainer>
<MainStack />
</NavigationContainer>
<Snackbar />
</>
);
};

Related

How can I navigate from login screen to a bottomtab screen?

How can I navigate to a bottomtab screen rather than a stack screen? The goal is to take the user to the main home page onPress of the sign in button. I initially created a Stack.Screen and added the homescreen component but that crashed the header and the bottom tab navigation and there was also the back button in the header which isn't supposed to be because the home screen is the main screen. Is there a way to navigate to the bottom tab screen from the sign in component? I'm a beginner by the way and also not so good at using stack overflow
if you're using react router than this may possible with useNavigate() and Link. Also you can add custom javascript window.location.href ="/pagename"
Usage of useNavigate() before return of function-
const navigate = useNavigate()
onClick = (e)=>(
e.preventDefault()
navigate('/home')
)
Usage of Link inside body-
<Link to="/home"></Link>
Usage of custom javascript inside body-
<button onClick = (()=>window.location.href="/home"))>Click me</button>
Hope you'll like the answer. But if you still face any issue just lemme know.
I suggest you to try an Authentication flow approch written by 'React-Navigator' API.
The main idea of that is using 2 Navigators.
Stack Navigator for 'Login'
Tab Navigator for pages which logged in users can see
However, to make this flow available, you need to add Global State Management library like Redux / React Context to handle which navigator is showing. Once the state is set, the app will auto select the navigator used. You don't need to call any function for navigation.
<NavigationContainer>
<Stack.Navigator>
{
!redux.isLoggedIn ?
<Stack.Group>
<Stack.Screen
name="auth"
component={Auth}
/>
</Stack.Group>
:
<Stack.Group>
<Stack.Screen
name="home"
component={YourHomeTabNavigator}
/>
</Stack.Group>
}
</Stack.Navigator>
</NavigationContainer>

React native partial modal

I am working on a react-native app using react navigation.
I want to add a partial modal that covers 30% of screen when pressing on one of the tabs in the bottom-tab, similar to the "+" tab in the YouTube app:
Youtube modal
I've tried to use react-native Modal component, but
I have problems with activating it from bottom tab
it covers whole screen
Any suggestions?
Thanks..
To answer your question 100% correct I'd need to know more details about your project but, I can try to explain how can be your logic to do this withou any libs.
You can create another component called "Start" where you're gonna put your Modal with absolute position above your navigator.
You can create a Modal that will be above your navigator:
export const Start(){
return(
<View style={{flex:1}}>
<Modal>
<View/>
</Modal>
<NavigatorComponent/>
</View>
)
}
This is going to work because when you put a component with absolute position above the other, this component stay in front of the below component. In your case, will stay in front of everything including the TabBar.
To the modal has just 30% of the height you just need to put in its styles the attribute height: '30%'.
In the initial component of your App (usually the index.js file), you just return the new Start component.
I hope you like my answer. Please, if you have more questions you can ask. Waiting for your feedback :).

How to disable swipe action in specific screen on react navigation 5?

im using react navigation 5 on my project, and somewhere in the project i need to make nested navigators like below:
*Stack Navigator
**Material top tab navigatior
***Material bottom tab navigator
**** Stack Navigator
My goal is, actually i want to have 3 static screens like instagram. On the left side will be Camera, then in the center actual content and in the right side something else. And only when you are in center i want to bottom tabs are visible thats why i created it like that. In this case in all the screens you can swipe right or left for reaching to camera or right component.
But what i want to do is, i want do "disable" swipe action in detail screens in center component. Becose center component which is material bottom tab navigator above, contains some stack navigators also, like posts, postDetail. and when i go to postDetail i want to disable swipe left or right action. Becouse in some details im using some swipeable elements like react native swiper etc.
I have tried to give gesturesEnabled: false , swipeEnabled: false in material bottom navigator as props but it doesn't work becouse it's a bottom tab navigator and doesn't take these params.
I also tried to catch state index and if its greater than 0 or 1 i would disable it but in material top tab navigator doesn't change the index when i go to postDetail for example. It's not working like previous version which is react navigation 4.
const BlogStack = createMaterialTopTabNavigator();
const BlogStackNavigator = ({ navigation, route }) => {
return (
<BlogStack.Navigator
initialRouteName="Blogs"
tabBarOptions={{
style: {
height: 0,
},
}}
//swipeEnabled={route.state && route.state.index > 0 ? false : true}
>
<BlogStack.Screen name="Camera" component={Camera} />
<BlogStack.Screen name="Blogs" component={Blog} />
<BlogStack.Screen name="Timeline" component={Profile} />
</BlogStack.Navigator>
);
};
Try setting gestureEnabled to false in Screen's options.
<Screen name={key} options={{gestureEnabled: false}} component={Component} />
You need to set gestureEnabled to false but it's not sent as a prop. You need to set it in the options prop. If you want to set it for all screens you can place it in the navigator like this:
<BlogStack.Navigator
initialRouteName="Blogs"
tabBarOptions={{
style: {
height: 0,
},
}}
screenOptions={{gestureEnabled: false}}
>
or for only specific screens:
<BlogStack.Screen name="Camera" options={{gestureEnabled: false}} component={Camera} />

How to prerender a component in react-navigation before switching to it?

Inside my StackNavigator, one of the components includes web content with a long loading time. However, this screen will only be shown late in my navigation flow.
How can I use this time to render my component in the background before finally switching to it?
I couldn't find anything comparable to ReactDOM.render in React Native that would allow me to render it manually.
I am not aware of any option in react-navigation to preload a screen that is not displayed, except maybe when the screen is part of a tab navigator.
Depending on what is slowing down the rendering, you might be able to do some actions in the first screen and later pass the results to the second screen using a navigation parameter.
For instance, if you are fetching data from an api in the second screen, you could fetch this data in the first screen and pass it to the second one:
this.props.navigation.navigate('SecondScreen', { data: this.data });
If it is a component, you could also try to build it in the first screen and pass it in the same fashion:
this.props.navigation.navigate('SecondScreen', { component: this.component });
If you are rendering a WebView in the second screen, what can help is to render the WebView in the first screen too, but with no width or height. The WebView will not be displayed but the website data will be fetched and cached, making the real render more efficient:
render() {
return (
<View>
<WebView source={{ uri: 'https://github.com/facebook/react-native' }} style={{ height: 0, width: 0 }} />
{this.renderCurrentScreen()}
</View>
);
}

How to open and close Shopify Polaris Modal using App-Bridge

I'm using Shopify Polaris #3.4.0 and App-Bridge #1.0.3. Also used shopify-node-app as a starting.
I initialize app-bridge by passing apiKey and shopOrigin values like so:
<AppProvider apiKey={apiKey} shopOrigin={shopOrigin}
<Switch>
<Route exact path='/admin' component={Dashboard} />
</Switch>
</AppProvider>
In my Dashboard component I have a Modal component:
<Modal
src='https://somewhere/',
title='title',
open={modalActive}
/>
I open the modal by setting the state to true for modalActive like so:
this.setState({modalActive: true});
Shopify Polaris Modal uses an iframe when src is used and in that view I have a submit form. I would like to close the Modal when the form is submitted. I have tried dispatching an action to close the modal using app-bridge, but honestly I'm confused and these are all recent releases so any help is appreciated.
Long story short pass a function to the Modal primaryAction prop. The core of this is child to parent component state changes. So more of a ReactJS question.
Alright, had a similar issue and it's a little embarrassing to admit this but hey if it saves you a half and hour then great.
Shopify's Modal docs use active to keep the state of the externally triggered modal. But don't forget to use open as the actual prop to the <Modal> component:
<Modal
open={active}
...rest of props
/>
...content
</Modal>