React Native : multiple Navigator navigationBar - react-native

I'm stuck with React Native.
I have a "Header" navigationBar, but I want to add another navigationBar to my Navigator component.
render() {
let currentRoute = this.props.route
return (
<Navigator
style={styles.container}
initialRoute={this.props.route}
renderScene={this.router.bind(this)}
navigationBar={<Header />} // << There, how can I simply add another navigationBar ?
/>
);
}
And here's the <Header/> component :
render() {
return <Navigator.NavigationBar
style={styles.navBarContainer}
navState={this.props.navState}
routeMapper={routeMapper}
/>
}
Now, I'm trying to add a <Footer/> component, which would render a similar component as <Header/>, in order to have 2 persistent navigation bar on my app.
How to achieve this ?

I also meet this question, and have resolved it. In React Native, it is not supported to add multiple navigationBar. But, if you want to add another "navigationBar", you can add this "navigationBar" as the sibling node of the Navigator, such as:
render() {
return (
<View style={styles.scene}>
<TopStatusBar
showBackIcon={false}
centerText={LocalizedStrings.appName}
rightIcon={require("../../res/icons/head.png")}
onRightPress={this._onHeadPress.bind(this)}
/>
<Navigator
initialRoute={ROUTE_STACK[0]}
renderScene={this._renderScene.bind(this)}
configureScene={() => Navigator.SceneConfigs.FadeAndroid}
navigationBar={
this.state.displayBottomTabBar ?
<BottomTabBar
ROUTE_STACK={ROUTE_STACK}
/>
:
null
}
onWillFocus={(route) => {
this.presentedRoute = route;
}}
sceneStyle={{flex: 1}}
/>
</View>
);
}
In the upper code, TopStatusBar is a composite component. It persists across scene transitions, just like the navigatorBar.
Good luck!

Related

React Navigation swipe between screens

I'm using React Navigation on React Native, how do I swipe between multiple screens?
I can only find an onPress solution that navigates me to a specific screen on button press, but I would like to just swipe left and right as well.
Your help would be super appreciated
I think you are willing to create a slider between screens
I think you can use react-native-snap-carousel
import Carousel from 'react-native-snap-carousel';
export class MyCarousel extends Component {
_renderItem = ({item, index}) => {
return (
<View style={styles.slide}>
<Text style={styles.title}>{ item.title }</Text>
</View>
);
}
render () {
return (
<Carousel
ref={(c) => { this._carousel = c; }}
data={this.state.entries}
renderItem={this._renderItem}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
/>
);
}
}

react native splash page warning

I have made an splash page looks like this:
export default class Splash extends Component {
performTimeConsumingTask = async () => {
return new Promise((resolve) =>
setTimeout(() => {
resolve('result');
}),
);
};
async componentDidMount() {
const data = await this.performTimeConsumingTask();
// const navigation = useNavigation();
if (data !== null) {
this.props.navigation.navigate('BottomMainNavgigation');
}
}
render() {
return (
<View style={styles.viewStyles}>
{/* <Text style={styles.textStyles}>Welcome</Text> */}
<Image
style={styles.tinyLogo}
source={{
uri: URL.logov2,
}}
/>
</View>
);
}
}
THen I use this like this, in my navigation:
const RootStackScreen = (props) => {
const [t] = useTranslation();
return (
<SplashRootStack.Navigator>
<SplashRootStack.Screen
name="Main"
component={Splash}
options={{headerShown: false, headerBackTitle: t('back')}}
/>
<SplashRootStack.Screen
name="BottomMainNavgigation"
component={BottomMainNavgigation}
options={{headerShown: false, headerBackTitle: t('back')}}
/>
</SplashRootStack.Navigator>
);
};
and also:
<PaperProvider theme={MyTheme}>
<NavigationContainer linking={linking} fallback={<Splash />}>
<RootStackScreen />
</NavigationContainer>
</PaperProvider>
and like this in my app.js:
const App = () => {
return (
<Provider store={store}>
<PersistGate loading={<Splash />} persistor={persistor}>
<Suspense fallback={<Splash />}>
<Navigation />
</Suspense>
</PersistGate>
</Provider>
);
};
export default App;
when I run the application it looks like this:
there is a warning :
I get this warning with id= 0, 1 and 2 and I get this warning also:
what have I donr incorrectly ad how can I remove these warnings, also when I load the app in the emulator, I get a white screen for few seconds before I get my own splash page and then to my app.
how can I do this better?
You are using Splash component in redux persist as a loader and in your Splash component there isn't any navigation prop available because it's a parent component and not the part of navigation tree you need to use switch navigator for the same purpose but with the current structure navigation will not work unless you move navigation part inside the navigator tree. Now the solution is,
Use only splash as a static UI component.
Move you navigation or componentDidMount logic inside the stack navigator.
Add simple Activity indicator as fallback.
<PersistGate
loading={<ActivityIndicator style={{top: '45%'}}
animating color={theme.appColor} size='large' />}
persistor={ReduxStore.persistor}>
<Navigator />
</PersistGate>
Your warnings
Undefined is not an object :
The problem is that you are using the Splash as the fallback component so until your deeplink is resolved Splash would be displayed and the Splash here is not part of navigation which will not get the 'navigation' prop so you are getting the warning.
Same for the other higher order components like PersistGate and suspense you can given the splash for everything and all this is outsider navigation.
resolution : Use the activity indicator instead of splash for the fallback
This is due to one of your middleware in redux taking longer, better check your redux middleware.
White screen,
this is whats causing the white screen maybe caused by the same reason as your middleware warning or the component did mount of the splash screen. And you have several providers so better remove one or two and check whats causing that.
You can check this sample to get an idea on using splash screens and authentication.
https://snack.expo.io/#guruparan/rnn-v5

Warning while using ListItem, FlatList inside ScrollView

I get this warning when I tried using Flatlist inside View but same error occurs:
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.
The component I am using FlatList inside is:
class About extends Component
{
constructor(props)
{
super(props);
this.state = {
leaders: LEADERS
};
}
render(){
const renderLeaders = ({item,index}) => {
return(
<ListItem
key = {index}
title = {item.name}
subtitle = {item.description}
hideChevron = {true}
leftAvatar = {{ source: require('./images/alberto.png') }}
/>
);
};
return(
<ScrollView>
<History />
<Card title = "Corporate Leadership">
<FlatList
data = {this.state.leaders}
renderItem = {renderLeaders}
keyExtractor = {item => item.id.toString()}
/>
</Card>
</ScrollView>
);
}
}
And can I use leader in place of item here? I tried using it but there was an error.
one way to hack this would be to use react-native-gesture-handler flatlist
it will sort of take over your parenting ScrollView if you absolutely need to have nested scrollers, at least that worked for me when i had this same problem.
As per second part, without delving too deep of what is what, try reading this https://www.barrymichaeldoyle.com/destructuring/#:~:text=Renaming%20Variables%20while%20Destructuring&text=In%20order%20to%20rename%20a,rename%20the%20destructured%20variable%20to or google any other theory on 'destructuring renaming'
if you absolutely need to rename 'item'.

How to hide the statusBar when react-native modal shown?

I want to hide the status bar, when modal window is shown.
My setup is as following, but it won't work as expected:
<StatusBar animated={true} hidden={true} translucent={true}>
Use statusBarTranslucent
If your status bar is translucent, you can set statusBarTranslucent to the modal.
Added since React Native 0.62
<Modal {...props} statusBarTranslucent>...</Modal>
Credit: https://github.com/react-native-modal/react-native-modal/issues/50#issuecomment-607535322
This is a known issue and there seems to be no official/React way to fix it yet. You can follow the discussion here:
https://github.com/facebook/react-native/issues/7474
I saw a post in this discussion which proposes a hack to hide it, but I haven't tried it on my project. You can also upvote this trick if it works for you.
<View style={styles.outerContainer}
<View style={styles.container}>
<StatusBar hidden={true}/>
<View style={styles.content}>
</View>
<Modal animation={fade} transparent={true}>
{/*Modal Contents Here*/}
</Modal>
</View>
A more solid fix may be changing the theme of activity in native android code.
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.ReactNative.AppCompat.Light.NoActionBar.FullScreen">
<!-- Customize your theme here. -->
</style>
<style name="AppTheme.Launcher">
<item name="android:windowBackground">#drawable/launch_screen</item>
</style>
</resources>
Credits go to Traviskn and mbashiq who proposed fixes above. I recommend you to subscribe that issue.
According to the documentations, you should be able to hide status bar in both iOS and Android using this
import {StatusBar} from 'react-native';
StatusBar.setHidden(true);
We can use the background of StatusBar to solve this problem easily but may not the best.
<Modal transparent>
{Platform.OS === 'android' ?
<StatusBar backgroundColor="rgba(0,0,0,0.5)"/>
: null
}
<View style={{backgroundColor: 'rgba(0,0,0,0.5)'}}>
// ModalContent here
</View>
</Modal>
Just use the same background and this problem can be solved.
I am actually facing the same issue for some time, I tried many solutions but I didn't get rid of this problem. I also tried to use native Android code to hide the StatusBar for a single component it works in other component but when I use it in modal it just not working. So, at last, I got a solution that works for me. I remove the modal view and replace it with react-navigation to navigate to a specific path and handle the back button using BackHandler component.
i achieve this creating a custom status bar component with a modal prop:
import React from 'react'
import { StatusBar } from 'react-native'
const MyStatusBar = (props) => {
const { backgroundColor } = props
const { barStyle } = props
const { translucent } = props
const { hidden } = props
const { showHideTransition } = props
const { modal } = props;
(modal !== undefined) ? StatusBar.setHidden(true) : StatusBar.setHidden(false)
return (
<StatusBar showHideTransition={showHideTransition} hidden={hidden} translucent={translucent} backgroundColor={backgroundColor} barStyle={barStyle} />
)
}
export default MyStatusBar
inside my base component modal prop is undefined so custom status bar is shown:
<MyStatusBar backgroundColor={theme.colors.primary} barStyle={'light-content'} />
and then calling inside the component who call the modal:
<MyStatusBar modal={modalVisible ? true : undefined} />
I think the root of my problem is the same, but it appeared a little different than how it is described above.
Expected behaviour: When the Modal becomes visible the StatusBar should hide.
const [showModal, setShowModal] = useState(false)
...
<Modal
visible={showModal}
>
<StatusBar hidden={showModal} />
...
Actual bahviour: Sometimes the StatusBardissapears as expected, other times just the StatusBar background color goes away and the actual StatusBar remains.
Workaround: Due to the flickering behaviour I think the problem is a racing condition of the native Android dialog. Therefore, I built a custom Modal component that uses the StatusBar imperative api to make sure the StatusBar hide call is made before the Modal appears. So far the Problem has not reappeared.
Here is the custom Modal component:
const Modal = ({ visible, children, ...rest }) => {
const [modalVisibility, setModalVisibility] = useState(false);
useEffect(() => {
if (visible) {
StatusBar.setHidden(true);
setModalVisibility(true);
} else {
StatusBar.setHidden(false);
setModalVisibility(false);
}
}, [visible]);
return (
<RNModal
visible={modalVisibility}
{...rest}
>
{children}
</RNModal>
);
};
export default Modal;
Hello you can try this
<View style={styles.outerContainer}
<View style={styles.container}>
<StatusBar hidden={true}/>
<View style={styles.content}>
</View>
<Modal animation={fade} transparent={true}>
{/* Contents Here*/}
</Modal>
</View>
<StatusBar backgroundColor={'transparent'} translucent={true} />

Adjacent JSX elements must be wrapped in an enclosing tag

I want to have a navigation bar at the bottom and a toolbar at the top of every page in my React-Native app. However, if I create these two elements in the index.ios.js file, I get the error: "Adjacent JSX elements must be wrapped in an enclosing tag". If I put tags surrounding the Navigator and NavBar I just see a blank screen in my app. What should I do? Here is what my render function looks like in index.ios.js
render() {
return (
<Navigator
initialRoute={{name: 'Login'}}
renderScene={this.renderScene}
navigationBar={
<Navigator.NavigationBar
style={ styles.nav }
routeMapper={ NavigationBarRouteMapper } />
}
/>
<NavBar />
);
}
As per React 16, if you wan't to avoid the <View> wrapping,
you can return multiple components from render as an array.
return ([
<Navigator key="navigator" />,
<NavBar key="navbar" />
]);
Or in a stateless ES6 component:
import React from 'react';
const Component = () => [
<Navigator key="navigator" />,
<NavBar key="navbar" />
];
export default Component;
Don't forget the key property as React needs (as for iteration on Array) to be able to discriminate your components.
Edit (Nov. 2018)
Your can also use React.Fragment shorthand:
render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}
When you wrap it in a view make sure you set the flex to 1. My guess is that the view you are giving it has no size and therefore the child elements are inheriting their size from the parent (which is 0)
Wrap both inside a View and give that outer View wrapper a style of flex 1. Example:
<View style={{flex: 1}}>
<Navigator
{. . .}
/>
<NavBar />
</View>