Hide NavBar on certain routes - React Router V4 - react-router-v4

I'm using react-router v4 and I'd like to hide the NavBar on certain routes. How can I hide the NavBar on the login page? I've tried a few different solutions but none seems to work. Some insight would be appreciated.
const App = appProps => (
<Router>
<ScrollToTop>
<Container fluid>
<NavBar {...appProps} />
<Switch>
<Route name="landing" path="/landing" component={LandingPage} {...appProps} />
<Route name="login" path="/login" component={LoginPage} />
</Switch>
</Container>
</ScrollToTop>
</Router>
);

You should have a layout component that renders the required components depending on the route.
const AppLayout = (props) => {
return (
<ScrollToTop>
<Container fluid>
{props.navBar ? React.createElement(props.navBar) : null}
{props.children}
</Container>
</ScrollToTop>
);
};
Then create the following route component that passes down its props the the layout:
const AppRoute = ({ component, ...routeProps }) => {
return (
<Route {...routeProps} render={(props) => {
return (
<AppLayout { ...props} {...routeProps}>
{React.createElement(component, props)}
</AppLayout>
);
}} />
);
};
Finally, update your App component so it looks like this:
const App = appProps => (
<Router>
<Switch>
<AppRoute name="landing" path="/landing" navBar={NavBar} component={LandingPage} {...appProps} />
<AppRoute name="login" path="/login" component={LoginPage} />
</Switch>
</Router>
);

Related

UI Kitten and initialRouteName

I am trying to set a specific tab to start the application. UI kitten's navigation, starts up with the first tab, and actually I want the tab that is in the second position to be the first to appear to the user. I can not find how to set the initialRoute withtin UI kittens Bottom tab bars. I post some of my code so it can be clear:
const { Navigator, Screen } = createBottomTabNavigator();
const BottomTabBar = ({ navigation, state }) => (
<View>
<Divider />
<BottomNavigation
appearance="noIndicator"
selectedIndex={state.index}
onSelect={(index) => navigation.navigate(state.routeNames[index])}
>
<BottomNavigationTab title="screen1" icon={icon1} />
<BottomNavigationTab title="screen2" icon={icon2} />
<BottomNavigationTab title="screen3" icon={icon3} />
</BottomNavigation>
</View>
);
export const BottomTabsNavigator = () => (
<Navigator tabBar={(props) => <BottomTabBar {...props} />}>
<Screen name="screen1" component={Screen1}/>
<Screen name="screen2" component={Screen2}/>
<Screen name="screen3" component={Screen3} />
</Navigator>
);
export const AppNavigator = () => {
return (
<SafeAreaView>
<NavigationContainer>
<Navigator headerMode='none' >
<Screen name={'BottomTabs'} component={BottomTabsNavigator} />
</Navigator>
</NavigationContainer>
</SafeAreaView>
)
};
I've tried in multiple positions but it doesn't seem to work.
Within the following component:
<Navigator tabBar={(props) => <BottomTabBar {...props} />}>
You need to use the following prop: initialRouteName, like so:
<Navigator initialRouteName={'namehere'} tabBar={(props) => <BottomTabBar {...props} />}>
This is telling the navigator what screen to start on when initially rendered! Hope this helps.
For anyone outside of this question that has landed on this page, you can specify what screen you want the navigator to "start" on by using the prop: initialRouteName. This then tells the navigator to use this as your landing page!

Native-base doesn't show footer component in my view React-native

I'm triyng to use the Footer component from native-base in my view, but i can't see nothing when i implement the code from: Footer component native-base
I don't know if maybe is a bug or if i need implement an aditional option in my code.
My code:
(I dont show Login.tsx because only use footer in Home view)'.
App.tsx
import {createStore} from 'redux';
import rootReducer from './Store/Reducers/Reducers';
const store = createStore(rootReducer);
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { loading: true };
}
async componentDidMount() {
await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
});
this.setState({ loading: false });
}
render(){
if (this.state.loading) {
return (
<Root>
<AppLoading />
</Root>
);
}
else {
return (
<Provider store={store}>
<Root>
<NavigationContainer>
<Navigator/>
</NavigationContainer>
</Root>
</Provider>
);
}
}
}
Navigator.tsx
import React from 'react'
import { createStackNavigator } from '#react-navigation/stack'
import Login from '../Views/Login'
import Home from '../Views/Home'
import Register from '../Views/Register'
const Stack = createStackNavigator();
const Navigator= () =>{
return (
<Stack.Navigator>
<Stack.Screen name="Login" component={Login} options={{headerShown:false}}/>
<Stack.Screen name="Home" component={Home} options={{title:'Home.'}}/>
<Stack.Screen name="Register" component={Register} options={{title:'Register.'}}/>
</Stack.Navigator>
);
}
export default Navigator;
Home.tsx (Only the footer here)
import React from 'react'
import {Footer, Icon, Button, Text, FooterTab, Container} from 'native-base'
import Styles from './Styles/HomeStyles'
import {connect} from 'react-redux'
const Home =(props) => {
const {users} = props;
return(
<Container style={Styles.container}>
{users.list !== undefined && users.list.length>0 ?
users.list.map(user=> (
<Text>Hello {user.nick}</Text>
))
: null
}
<Footer>
<FooterTab>
<Button vertical>
<Icon name="apps" />
<Text>Apps</Text>
</Button>
<Button vertical>
<Icon name="camera" />
<Text>Camera</Text>
</Button>
<Button vertical active>
<Icon active name="navigate" />
<Text>Navigate</Text>
</Button>
<Button vertical>
<Icon name="person" />
<Text>Contact</Text>
</Button>
</FooterTab>
</Footer>
</Container>
);
}
const mapStateToProps=(state)=>{
const {users} = state;
return {users};
}
export default connect(mapStateToProps)(Home);
The result in Home:
Try add Content before Footer, like that, Content is also imported from native-base, if it's still not working, try removing the style of the container
<Container>
<Content><Text>dsdsds</Text></Content>
<Footer>
<Button vertical>
<Icon name="apps" />
<Text>Apps</Text>
</Button>
</Footer>
</Container>

How to create custom header options for each screen multi stack navigation react native?

I am looking for a way to set custom header options (styling, icons, enabling/disabling back button, left and right options for the header) for each of the screen in the stacks, while maintaining multi-stack architecture for my app in react native?
This is how my App.js looks right now, and I am willing to change it if need be.
const Stack = createStackNavigator();
const App = () => {
const ref = React.useRef();
const { getInitialState } = useLinking(ref, {
prefixes: ['FoodApp://'],
});
const AuthStack = createStackNavigator();
function AuthStackScreen() {
return (
<AuthStack.Navigator>
<AuthStack.Screen name="LogIn" component={LogIn} />
<AuthStack.Screen name="SignUp" component={SignUp} />
</AuthStack.Navigator>
);
}
const AppStack = createStackNavigator();
//I'd like to set different header options for each of the screen here
function AppStackScreen() {
return (
<AppStack.Navigator>
<AppStack.Screen name="MenuCategoryItems" component={MenuCategoryItems} />
<AppStack.Screen name="Delivery" component={Delivery} />
<AppStack.Screen name="Account" component={Account} />
<AppStack.Screen name="Notification" component={Notification} />
<AppStack.Screen name="Cart" component={Cart} />
</AppStack.Navigator>
);
}
//TODO: pass customized bar components
const Tab = createBottomTabNavigator();
//I'd like to set different header options for each of the screen here
function Tabs(){
return (
<Tab.Navigator tabBar={props => <BottomMenu {...props} />}>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Delivery" component={Delivery} />
<Tab.Screen name="Account" component={Account} />
<Tab.Screen name="Notification" component={Notification} />
<Tab.Screen name="Cart" component={Cart} />
</Tab.Navigator>
);
}
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Tabs} />
<Stack.Screen name="AppStack" component={AppStackScreen} />
/*Should I place something else here so that I have access to both AppStack and Tabs navigations?*/
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
Not sure if this is what you need but here is how I customize some "borderColor" value for my header component.
You can pass any options you want via the setOptions method of the navigation component. It will be populated in the scene.descriptor.options parameter.
Below an example of how I am using it in my app.
the header options for my screen/navigator.
header: ({scene, previous, navigation}) => {
const {options} = scene.descriptor;
let borderColor = options.borderColor ?? 'yellow';
if (scene.route.name.startsWith('Test')) {
borderColor = 'blue';
}
return <HeaderBar options={options}
title={title}
previous={true}
navigation={navigation}
borderColor={borderColor}
/>;
}
And in any of the screens components I can use
useLayoutEffect(() => {
navigation.setOptions({
borderColor: 'orange'
})
}, [ navigation ])
Now, my <HeaderBar> component will receive a prop borderColor whose value is 'orange'.
export const HeaderBar = ({ options, title, previous, navigation, borderColor = 'yellow' }) => {
[...]
console.log(borderColor); // orange
}
As you can see, my HeaderBar component also receive the full options as a prop, therefore I could skip the borderColor prop and check the options inside the header component itself.
Like so
export const HeaderBar = ({ options, title, previous, navigation }) => {
const { borderColor } = options;
[...]
}
Hope it will help you if not too late.
Well. You could hide header default of react-navigation in your stack.
function AppStackScreen() {
return (
<AppStack.Navigator headerMode={'none'}>
<AppStack.Screen name="MenuCategoryItems" component={MenuCategoryItems} />
<AppStack.Screen name="Delivery" component={Delivery} />
<AppStack.Screen name="Account" component={Account} />
<AppStack.Screen name="Notification" component={Notification} />
<AppStack.Screen name="Cart" component={Cart} />
</AppStack.Navigator>
Then, you could custom header component and import it in each your screen.
Sorry because my EL. hope help U.

Is it possible to pass the goBack() function as a parameter

I have a function AccountScreen. From this screen I would like to be able to navigate.goBack(). I tried following the guide here on how to go back to a previous screen but I am getting an error.
Here is my code:
AccountScreen.js
const BackButton = styled.Button`
`;
function AccountScreen({doThis}) {
return(
<Root>
<BackButton title="" onPress={() => doThis} />
<Text>Account</Text>
</Root>
)
};
export default AccountScreen;
navigations.js
const createProfileDrawer = ({navigation}) =>
<Drawer.Navigator>
<Drawer.Screen name="Profile" component={ProfileScreen}/>
<Drawer.Screen name="Account"
component={AccountScreen(navigation.goBack())} />
</Drawer.Navigator>
So when I try and pass it like this I get an error The action 'GO_BACK' was not handled by any navigator. Is it possible to pass a function like this?
Try making the following changes:
in AccountScreen.js:
import { useNavigation } from '#react-navigation/native';
function AccountScreen() {
const navigation = useNavigation();
return(
<Root>
<BackButton title="" onPress={() => navigation.openDrawer()} />
in navigations.js:
<Drawer.Screen name="Account" component={AccountScreen} />
Note that action you want is likely not 'goBack' but 'openDrawer'.

React Router v4 & CSS Transition Group

I have a simple example of react-router v4 & route transitions. It follows the example shown at https://reacttraining.com/react-router/web/example/animated-transitions. The result, however, is only the last route is shown. The others are just blank. https://codesandbox.io/s/r0PvB30wk.
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import { CSSTransitionGroup } from 'react-transition-group'
import About from './components/About';
import Home from './components/Home';
import Topics from './components/Topics';
import './styles.css'
const BasicExample = () => (
<Router>
<Route render={({ location }) => (
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr />
<CSSTransitionGroup
transitionEnterTimeout={300}
transitionLeaveTimeout={300}
transitionName="fade"
>
<Route exact path="/" component={Home} location={location} key={location.key} />
<Route path="/about" component={About} location={location} key={location.key} />
<Route path="/topics" component={Topics} location={location} key={location.key} />
</CSSTransitionGroup>
</div>
)}/>
</Router>
);
render(<BasicExample />, document.body);
For anyone interested, the only way I could get this to work was to use a <switch> from react-router.
import React from 'react'
import { render } from 'react-dom'
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'
import { CSSTransitionGroup } from 'react-transition-group'
import About from './components/About'
import Home from './components/Home'
import Topics from './components/Topics'
import './styles.css'
const BasicExample = () => (
<Router>
<Route render={({ location, history, match }) => (
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr />
<CSSTransitionGroup
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
transitionName="fade"
>
<Switch key={location.key} location={location}>
<Route exact path="/" component={Home} location={location} key={location.key} />
<Route path="/about" component={About} location={location} key={location.key} />
<Route path="/topics" component={Topics} location={location} key={location.key} />
</Switch>
</CSSTransitionGroup>
</div>
)}/>
</Router>
)
render(<BasicExample />, document.body)
You have to write tags like code, otherwise they disappear... So you ment <Switch>? :)