A lightweight, custom navigation and routing solution for React and React Native applications, with no external dependencies.
- Simple and lightweight navigation context
- Navigation history tracking
- Dynamic route parameter support
- Programmatic navigation with
navigateTo
,goBack
, andgoForward
- Retrieve current URI and navigation history
- Clear navigation history
- Check if navigation backward/forward is possible
npm install @payello-ui/react-router
# or
yarn add @payello-ui/react-router
Wrap your application in the provided NavigationProvider
to make the navigation context available to all components.
import React from 'react';
import { NavigationProvider } from '@payello-ui/react-router';
import AppContent from './AppContent';
const App = () => {
return (
<NavigationProvider>
<AppContent />
</NavigationProvider>
);
};
export default App;
Define routes using the Route
component and use the Router
component to specify where these routes should be rendered.
The Router
component must be inside a NavigationProvider
, or it will throw an error.
import React from 'react';
import { Router, Route } from '@payello-ui/react-router';
import Home from './screens/Home';
import Profile from './screens/Profile';
import NotFound from './screens/NotFound';
const AppContent = () => {
return (
<Router notFound={NotFound} base="/">
<Route path="home" component={Home} />
<Route path="profile/:id" component={Profile} />
</Router>
);
};
Navigate between screens using the useNavigation
hook.
import React from 'react';
import { View, Button } from 'react-native';
import { useNavigation } from '@payello-ui/react-router';
const MyComponent = () => {
const navigation = useNavigation();
return (
<View>
<Button title="Go Home" onPress={() => navigation.navigateTo('/home')} />
<Button title="Go Back" onPress={navigation.goBack} />
</View>
);
};
-
Static Paths
- Matches a path exactly
- Example:
"/"
- Matches the root path exactly. - Example:
"/about"
- Matches the/about
path exactly.
-
Named Parameters
- Named Parameters can be used to extract information from a path. For example, you can include IDs or usernames in paths. These parameters will be passed as props to the component.
- By adding
+
after the parameter you can make it 'greedy'. This means it will capture everything after it. - Example:
"/users/:id"
- Matches a path after/users/
like/users/adam
or/users/123
, but does not match anything after a further/
such asusers/123/info
- Example:
"/files/:path+"
- Matches any path beginning with/files/
, such as/files/documents/reports/summary.pdf
-
Wildcards
- Wildcards can be used to allow for anything to be included in a path. This is useful for catch-all routes where the specifics of the path are not as important.
- Example:
/docs/*
- Matches anything beginning with/docs/
-
Regex
- Regex can be used to allow for advanced path matching.
- Example:
"/posts/(?<postId>\\d+)?/edit"
- This pattern will match both/posts/123/edit
and/posts/edit
, with the postId being optional. - Example:
"/images/(?<imageName>[^.]+)\\.png"
- This pattern will match any URL starting with/images/
and ending with.png
, capturing the filename (without the extension) as imageName.
To use parameters in paths, include them in the path and then access them from the component props.
interface ProfileProps {
id: string; // The prop name should match the named parameter in the route path
}
const Profile: React.FC<ProfileProps> = ({ id }) => {
return (
<View>
<Text>Profile Screen</Text>
<Text>User ID: {id}</Text>
</View>
);
};
/**
* The below example shows how to navigate to Profile with props { id: '123' }
*/
const NavigateToProfileButton = () => {
const { navigateTo } = useNavigation();
return <Button title="View Profile" onPress={() => {
const userId = '123'; // Replace with dynamic value as needed
navigateTo(`/profile/${userId}`);
}} />;
};
You can also use a RegExp as a path, which allows you to use a custom regular expression (regex) for path matching.
In the example below we allow userId to be an optional parameter. This matches both /users
and /users/:userId
.
// Route definition using regex
const userRouteRegex = new RegExp("^/users(?:/(?<userId>\\d+))?$");
// Within your Routes component
const AppContent = () => {
return (
<Router>
<Route path={userRouteRegex} component={UserScreen} />
</Router>
)
}
Provider component to wrap around your application to provide navigation context.
It takes the following props:
-
defaultUri
: A default URI to initialize with
Component to define where routes should be rendered. It should wrap around Route
components.
It takes the following props:
-
base
: A base path to prepend infront of all routes -
notFound
: The component to render when no routes match.
Component to define a single route.
It takes the following props:
-
path
: The path pattern to match against the current URI. -
component
: The component to render when the route matches.
Hook to access the navigation context.
It provides the following methods:
-
navigateTo(path: string)
: Navigate to the provided path. -
goBack()
: Navigate to the previous path in history. -
goForward()
: Navigate to the next path in history. -
getCurrentUri()
: Get the current path without navigating. -
getNavigationHistory()
: Get the navigation history. -
clearHistory()
: Clear the navigation history. -
isBackEnabled()
: Check if backward navigation is possible. -
isForwardEnabled()
: Check if forward navigation is possible.
The NavigationListener
component enables developers to easily integrate navigation state changes into their application logic by providing callback props.
To use the NavigationListener
component, you must first import it into your component file. Then, you can include it in your component's render method or return statement, providing the necessary callbacks for monitoring navigation changes:
import { NavigationListener } from "<path-to-the-component>";
<NavigationListener
onUriChanged={(uri) => console.log(`New URI: ${uri}`)}
onBackEnabledChanged={(isEnabled) => console.log(`Back navigation is ${isEnabled ? 'enabled' : 'disabled'}`)}
onForwardEnabledChanged={(isEnabled) => console.log(`Forward navigation is ${isEnabled ? 'enabled' : 'disabled'}`)}
/>
Contributions are welcome! If you'd like to contribute, please fork the repository and create a pull request with your changes. For major changes, please open an issue first to discuss what you would like to change.