Simple and fast navigation for react-native
Still under development
Note: Needs
react-native-redash
,react-native-reanimated
,react-native-gesture-handler
!
Well, in most cases I guess the best option this to choose one of above but I created this lib so I could create apps faster with less worry about the navigation part.
This lib is super flexible. The only required component to use is NavigationProvider
. The rest is just there for getting started faster.
- Supports left-to-right transitions for ios and android
- Same transitions on both ios and android
- Drawer support
- Tabs support
- Supports push, replace and pop screens
- Regular screens
- Half panels
- Modals
- Layovers
Follow the instructions how to install react-native-gesture-handler
and react-native-reanimated
. Nothing else is required. Read Usage to get started using the navigation.
import React from 'react';
import { View, Text, Button } from 'react-native';
import { FontAwesome } from '@expo/vector-icons';
import {
Screen,
NavigationProvider,
Tabs,
useRouter,
} from 'react-native-easy-navigation';
const Home = () => {
const router = useRouter();
return (
<Screen title="Home">
<Button
onPress={() => router.navigateToArticle({ title: 'Article 1', id: 1 })}
title="Go to Article 1"
/>
<Button
onPress={() => router.navigateToArticle({ title: 'Article 2', id: 2 })}
title="Go to Article 2"
/>
</Screen>
);
};
const Profile = () => {
const router = useRouter();
return (
<Screen title="Profile">
<Button
onPress={() =>
router.navigateToMyModal({
text: 'Modal: This is a prop passed to the Modal screen',
})
}
title="Open modal"
/>
<Button
onPress={() =>
router.navigateToMyHalfPanel({
text: 'HalfPanel: This is a prop passed to the Modal screen',
})
}
title="Open half panel"
/>
</Screen>
);
};
const Article = ({ title, id }) => {
const router = useRouter();
return (
<Screen title={title || 'Article'}>
<Text>Fetch article with ID = {id}</Text>
<Button onPress={router.pop} title="Custom go back button" />
<Button
onPress={() =>
router.replace('Article', {
props: { title: 'Article 3 - Replaced', id: 3 },
})
}
title="Replace with Article 3"
/>
<Button
onPress={() =>
router.push('Article', {
props: { title: 'Article 4 - Push', id: 3 },
})
}
title="Push with Article 4"
/>
<Button
onPress={() =>
router.push('Article', {
props: { title: 'Article 4 - Push', id: 3 },
})
}
title="Push with Article 4"
/>
</Screen>
);
};
const Modal = ({ text, type }) => {
return (
<Screen title={type}>
<Text>{text}</Text>
</Screen>
);
};
const Drawer = ({ text, type }) => {
return (
<View style={{ flex: 1 }}>
<Text>My drawer</Text>
</View>
);
};
const App = () => {
return (
<NavigationProvider
initial="Home"
routes={{
Home: { Component: Home },
Profile: {
Component: Profile,
statusBar: {
barStyle: 'light-content',
},
header: {
backgroundColor: '#000',
color: '#fff',
},
},
Article: { Component: Article },
Drawer: { Component: Drawer },
Modal: { Component: Modal },
}}
router={{
// Creates helper functions that we can get from `useRouter`-hook
// The params to the functions will be passed as props to the component
// Ex. `navigateToArticle({ id: 1, title: 'My article' })`
navigateToHome: { name: 'Home' },
navigateToProfile: { name: 'Profile' },
navigateToArticle: { name: 'Article' },
navigateToMyModal: { name: 'Modal' },
navigateToMyHalfPanel: { name: 'Modal' },
openDrawer: { name: 'Drawer', mode: 'drawer' },
}}
renderTab={route => {
// Will be called for each route
// If current route is Article we do not want to display the tabs
if (route.name === 'Article') {
return null;
}
// You can also create an array of all your tab items and then just map them.
// Tabs and Tabs.Item is just some helper components,
// You can easily create your own and then navigate to what ever you want
return (
<Tabs>
<Tabs.Item
route="Home"
icon={active => (
<FontAwesome
name="home"
size={26}
color={active ? '#007aff' : 'black'}
/>
)}
label={active => (
<Text style={{ color: active ? '#007aff' : 'black' }}>
Home
</Text>
)}
badge={() => <Tabs.Badge number={3} />}
/>
<Tabs.Item
route="Profile"
icon={active => (
<FontAwesome
name="user"
size={26}
color={active ? '#007aff' : 'black'}
/>
)}
label={active => (
<Text style={{ color: active ? '#007aff' : 'black' }}>
Home
</Text>
)}
badge={() => <Tabs.Badge number={3} />}
/>
</Tabs>
);
}}
/>
);
};
<NavigationProvider
router={{
// define shortcuts naviigation functions
navigateToArticle: {
name: 'Article'
},
}}
routes={{
Home: {
name: 'Home',
statusBar: {
barStyle: 'light-content|dark-content'
},
mode: 'replace|push|drawer|overlay|half-panel|modal',
// ignore header if you don't wrap your views with the <Screen> component
header: {
backgroundColor: '#000',
color: '#fff',
}
},
Article: {
name: 'Article',
},
}}
// renderTab gets called for each route
// here you can do some conditional render
renderTab={(route, router) => {
if (route.name !== 'Home') {
return null
}
return (
<Tabs>
<Tabs.Item
route="Home"
icon={active => (<Icon name="home"/>)}
label={active => <Text>Home</Text>)}
badge={() => <Tabs.Badge number={3} />}
/>
</Tabs>
)
}}
>
You can wrap all your main views with the Screen
component. This component will add a header with a title and a back button (if you are deeper then the first screen).
const Home = () => <Screen title="Home">{/* rest of your view */}</Screen>;
This is help full to get information from the screen you are at.
const Home = () => {
const {
showBackButton,
screen: {
id,
name,
mode,
animated,
statusBar: { barStyle },
header: { backgroundColor, color },
},
} = useScreen();
return null;
};
If you want to navigate this is the hook!
const Home = () => {
const {
push,
pop,
replace,
reset,
// and all the shortcuts you defined in <NavigationProvider router={} />
navigateToArticle,
} = useRouter();
return (
<>
<Button
title="Push"
onPress={() =>
push('Article', {
props: { id: 1 },
mode: '',
statusBar: {},
header: {},
animated: true,
})
}
/>
<Button title="Shortcut" onPress={() => navigateToArticle({ id: 1 })} />
</>
);
};