Skip to content

Commit

Permalink
chore(hooks): move hooks to more readible files
Browse files Browse the repository at this point in the history
Here's a brief overview of each hook:

1. `useComponentId` - This hook allows you to get the unique component ID from the current route.
2. `useLinking` - This hook provides functionality for linking between routes in your application.
3. `useModal` - This hook manages modals within your application, allowing you to open and close them as needed.
4. `useNavigator` - This hook provides a way to navigate through the application's history.
5. `usePathParams` - This hook allows you to access the dynamic path parameters from the current route.
6. `useQueryParams` - This hook enables you to access the query parameters from the current URL.
7. `useRoute` - This hook retrieves the current router state from the RouterContext.
8. `useRouteData` - This hook allows you to retrieve the router data associated with the current route.
  • Loading branch information
crherman7 committed Nov 12, 2024
1 parent e902645 commit 263da05
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 213 deletions.
36 changes: 36 additions & 0 deletions packages/app-router/src/hooks/useComponentId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {useContext} from 'react';

import {ComponentIdContext} from '../context';

/**
* Custom hook to access the Component ID context.
*
* @returns {string} The current component ID from the ComponentIdContext.
* @throws Will throw an error if the hook is used outside of a ComponentIdContext.Provider.
*
* @example
* ```tsx
* import { useComponentId } from 'path-to-hooks/useComponentId';
*
* function MyComponent() {
* const componentId = useComponentId();
*
* return (
* <div>
* <p>Component ID: {componentId}</p>
* </div>
* );
* }
* ```
*/
export function useComponentId(): string {
const state = useContext(ComponentIdContext);

if (!state) {
throw new Error(
'useComponentId must be used within a ComponentIdContext.Provider',
);
}

return state;
}
66 changes: 66 additions & 0 deletions packages/app-router/src/hooks/useLinking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {useEffect} from 'react';
import {Linking} from 'react-native';
import urlParse from 'url-parse';

import {useNavigator} from './useNavigator';

/**
* A custom hook that manages deep linking by listening for URL changes
* and navigating accordingly using a navigator.
*
* @example
* function App() {
* useLinking();
*
* return <YourAppComponent />;
* }
*
* // This hook will automatically handle incoming deep links and navigate
* // based on the URL, such as `yourapp://path?query=param`.
*/
export function useLinking() {
const navigator = useNavigator();

/**
* Handles the URL passed from deep linking and navigates to the correct screen.
*
* @param {Object} params - Parameters object.
* @param {string | null} params.url - The URL to be processed.
*
* @example
* callback({ url: 'yourapp://profile?user=123' });
*/
function callback({url}: {url: string | null}) {
if (!url) return;

try {
const {pathname, query} = urlParse(url);

// Navigates to the parsed URL's pathname and search params
navigator.open(pathname + query);
} catch (e) {
// Handle the error (e.g., log it)
}
}

useEffect(() => {
// Check the initial URL when the app is launched
(async function () {
try {
const url = await Linking.getInitialURL();

callback({url});
} catch (e) {
// Handle the error (e.g., log it)
}
})();

// Listen for any URL events and handle them with the callback
const subscription = Linking.addEventListener('url', callback);

// Cleanup the event listener when the component unmounts
return () => {
subscription.remove();
};
}, []);
}
53 changes: 53 additions & 0 deletions packages/app-router/src/hooks/useModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {useContext} from 'react';

import {ModalContext} from '../context';

import {useComponentId} from './useComponentId';

/**
* Hook to interact with a modal's state within the context of a `ModalContext.Provider`.
* Provides access to the modal's data and functions to resolve or reject the modal.
*
* @template T - The type of the data passed to the modal.
* @template U - The type of the result returned when the modal is resolved.
*
* @throws {Error} If the hook is used outside of a `ModalContext.Provider`.
*
* @returns {{ resolve: (result: U) => void; reject: () => void }} An object containing the modal's data, a `resolve` function to return a result, and a `reject` function to close the modal without returning a result.
*
* @example
* ```typescript
* // Using useModal in a component
* const { resolve, reject } = useModal<MyDataType, MyResultType>();
*
* // Resolve the modal with a result
* const handleConfirm = () => {
* resolve({ success: true });
* };
*
* // Reject the modal without returning a result
* const handleCancel = () => {
* reject();
* };
* ```
*/
export function useModal<T, U>() {
// Access the current modal state from the ModalContext
const state = useContext(ModalContext);

// Get the unique component ID of the modal
const componentId = useComponentId();

// Ensure the hook is used within a ModalContext.Provider
if (!state) {
throw new Error('useModal must be used inside a ModalContext.Provider');
}

return {
// A function to resolve the modal with a result of type U
resolve: state.resolve(componentId) as (result: U) => void,

// A function to reject the modal, closing it without returning a result
reject: state.reject(componentId) as () => void,
};
}
Loading

0 comments on commit 263da05

Please sign in to comment.