> Markdown version of [Hilla](https://vaadin.com/docs/v24/building-apps/views/pass-data/route-parameters/hilla). Section index: [llms.txt](https://vaadin.com/docs/v24/building-apps/llms.txt)

# Route Parameters in Hilla

In this guide, you’ll learn how to create a view that accepts a single route parameter. You’ll also explore the differences between required, optional, and wildcard route parameters.

## <a id="required-route-parameters"></a>Required Route Parameters

To create a Hilla view that accepts a required route parameter, you need to define the parameter name as the view name placed between curly braces (`{}`) followed by the `.tsx` suffix. For example, to create a view that accepts a required `productId` parameter, you should name the view `{productId}.tsx`. The directory structure under the `views` looks like this:

```
views/
└── products/
    └── {productId}.tsx (1)
```

1. The view file that accepts the `productId` parameter. The route is in the form of `/products/{productId}`, where `productId` is a required parameter. Routes such as `/products/123`, `/products/prd222`, etc., match this view. Trying to navigate to `/products` results in a 404 Not Found error unless a view matching the route is defined.

Though it is technically possible to define the views with parameters directly under the `views` directory, it is recommended to use subdirectories to keep the views organized.

The routing system also supports having parameters in the middle of the route, which means the directories can also have their names defined with a `{param-name}` convention. Here is an example of a view that accepts a required `productId` parameter:

```
views/
└── products
    └── {productId} (1)
        └── edit.tsx
```

1. The directory where all its children files have the `productId` parameter in the middle of their routes. The route is in the form of `/products/{productId}/edit`, where `productId` acts as a placeholder for the required parameter, in this case, the product ID. Routes such as `/products/123/edit`, `/products/prd222/edit`, etc., match this view. Trying to navigate to `/products/edit` results in a 404 Not Found error unless a view matching the route is defined.

### <a id="accessing-route-parameter-value"></a>Accessing Route Parameter Value

To access the route parameter in the view, use the `useParams` hook from `react-router` in your component. Here is an example of a view that accepts a required `productId` parameter:

views/products/{productId}.tsx

```tsx
// tag::snippet[]
import { useParams } from 'react-router';
// end::snippet[]

export default function ProductView() {
// tag::snippet[]
  const { productId } = useParams(); (1)
// end::snippet[]

  return (
    <>
        <h1>Product Details</h1>
        <p>Product ID: {productId}</p>
    </>
  );
}
```

1. The `useParams` hook returns an object containing the route parameters. In this case, the `productId` parameter is extracted from the object and stored in a variable.

### <a id="passing-route-parameter"></a>Passing Route Parameter

To navigate to a view that accepts a route parameter, use the `NavLink` component from `react-router`. Here is an example of how to create a link to a view located at `/products/123`:

```tsx
import { NavLink } from 'react-router';
...
<NavLink to="/products/123">Product 123</NavLink>
```

Another way is to use the `useNavigate` hook to navigate programmatically. Here is an example of how to use `useNavigate` for programmatic navigation:

```tsx
// tag::snippet[]
import { useNavigate } from 'react-router';
// end::snippet[]

function MyComponent() {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/products/123');
  };

  return (
    <button onClick={handleClick}>
      Go to Product 123
    </button>
  );
}
```

By using either of the above methods, you can navigate to the `/views/products/{productId}.tsx` view that accepts the `productId` route parameter. If you navigate to `/products/123`, the `productId` parameter is extracted and used in the view to fetch the product details for the given ID.

If a parameter is expected in the middle of the route, the method for navigating to the view is the same. For example, to navigate to `/products/123/edit`, use the same methods as above. The `useParams` hook extracts the `productId` parameter from the route, and the view fetches the product details for the given ID.

## <a id="optional-route-parameters"></a>Optional Route Parameters

Views can also have optional route parameters. This means that the view can be navigated to with or without the parameter. To make a route parameter optional, use double curly braces around the parameter name when naming the view file. For example, to create a view that accepts an optional `categoryName` parameter, name the view `{{categoryName}}.tsx`. The directory structure under the `views` looks like this:

```
views/
└── products
    └── {{categoryName}}.tsx (1)
```

1. The view file that accepts the `categoryName` optional parameter. The route for this view is in the form of `/products/{{categoryName}}`, where `categoryName` is an optional parameter. Routes such as `/products`, `/products/electronics`, `/products/clothing`, etc., match this view. Note that a view with an optional parameter should be able to handle both cases when the parameter is present and when it is not. Here is an example of a view that accepts an optional `categoryName` parameter:

views/products/{{categoryName}}.tsx

```tsx
import { useParams } from "react-router";
import { ProductService } from "Frontend/generated/endpoints.js";
import { useEffect } from "react";
import { useSignal } from "@vaadin/hilla-react-signals";

export default function ProductByCategoriesView() {
// tag::snippet[]
  const { categoryName } = useParams(); (1)
// end::snippet[]
  const products = useSignal<string[]>([]);

  useEffect(() => {
// tag::snippet[]
    if (categoryName == undefined) { (2)
// end::snippet[]
      ProductService.allProducts().then((data) => products.value = data);
    } else {
      ProductService.productsInCategory(categoryName).then((data) => products.value = data);
    }
  }, []);

  return (
    <>
      <h3>Products from {categoryName ? `'${categoryName}' category` : "all categories"}:</h3>
      <div>
        <ul>{products.value.map((product) => (
          <li key={product}>{product}</li>
        ))}</ul>
      </div>
    </>
  );
}
```

1. The `useParams` hook returns an object containing the route parameters. In this case, the `categoryName` parameter is extracted from the object and stored in a variable.

2. The `categoryName` parameter is checked to determine whether it is present or not. If it is not present, all products are fetched. Otherwise, products in the specified category are fetched.

In the above example, the `ProductByCategoriesView` fetches all products when the `categoryName` parameter is not present. When the `categoryName` parameter is present, it fetches the products in the specified category. The view displays the products in the specified category or all products if the `categoryName` parameter is not present.

## <a id="wildcard-route-parameters"></a>Wildcard Route Parameters

Wildcard route parameters are used to match any number of URL segments. This means when a URL cannot be matched with the other defined routes, the wildcard route is picked as the fallback to handle the navigation. One of the common cases of defining wildcard route parameters when defining the routes in a Hilla application is to properly handle the navigation of users when the route is not found. As the default way of defining the routes is through defining the view files and proper directory structure, adding wildcard route parameters should be done by defining the file name as `{…​wildcard}.tsx`. The literal value `wildcard` can be anything that is supported by the filesystem as the filename, but Vaadin recommends to use the `{…​wildcard}.tsx` as a conventional standard to make it more readable and intuitive. An example of a view that accepts a wildcard route parameter is shown below:

```
views/
├── @index.tsx
├── about.tsx
├── contact-us.tsx
└── {...wildcard}.tsx (1)
```

1. The view file that accepts the wildcard route parameter.

The routes that are matched with this view depends on the other defined routes. In this case the `/`, `/about`, and `/contact-us` are mapped to their respective views, and if the user tries to navigate to any other routes such as `/123`, `/orders`, or even `/about/789`, then the `{…​wildcard}.tsx` is matched as the fallback, accepting the whole unmatched segment of the URL as the wildcard parameter. The view can then handle the navigation and display a custom 404 Not Found page or redirect the user to the home page. Here is an example of a view that accepts a wildcard route parameter:

views/{…​wildcard}.tsx

```tsx
import { NavLink, useParams } from "react-router";

export default function WildcardView() {
  const wildcard = useParams()['*']; (1)
  return (
    <>
      <h3>Page Not Found!</h3>
      <div>
        The '<b>/{wildcard}</b>' route does not exist.
        Go back to the <NavLink to="/">home page</NavLink>.
      </div>
    </>
  );
}
```

1. The wildcard route parameter can be extracted using the `useParams` hook, which is stored in the `params` object with the ``**(asterisk) as the key. The matched wildcard parameters can have many segments, and all the segments is extracted at once when reading the `params` object with the ``**(asterisk) as the key.
