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 })} />
</>
);
};