4. Basic example

Now that we know how to use urlBuilder and useQueryParams let’s see it in action.

Here’s a basic example containing a Dashboard component which uses both query params and path parameters.

4.1 Dashboard

There are two options; a hook called useQueryParams and a Higher Order component called withQueryParams. The preferred solution is useQueryParams because it avoids a Higher order Component.

4.1.1 via useQueryParams

// Dashboard.tsx
import React from 'react';
import { useParams, useLocation } from 'react-router';
import { Url, useQueryParams, urlBuilder } from '@42.nl/react-url';

type DashboardPathParams = {
  id: string /* All path params are strings */;
}

type DashboardQueryParams = {
  page: number;
  query: string;
}

export function defaultDashboardQueryParams(): DashboardQueryParams {
  return {
    page: 1,
    query: '',
  };
}

/* 
  By extending RouteComponentProps we get the standard props that
  react-router adds when the component in a route.
*/
export default function Dashboard() {
  /* The `id` is a string which can be found on the params. */
  const { id } = useParams<DashboardPathParams>();
  const location = useLocation();

  const queryParams = useQueryParams({
    location,
    defaultQueryParams: defaultDashboardQueryParams(),
    debugName: 'Dashboard',
  });

  const { page, query } = queryParams;

  return (
    <div>
      <h1>
        Hello {id} You are on page {page} with query {query}.
      </h1>
    </div>
  );
}

export const DASHBOARD_URL = '/dashboard/:id';

export function toDashboard(pathParams: DashboardPathParams, queryParams?: Partial<DashboardQueryParams>): Url {
  return urlBuilder({
    url: DASHBOARD_URL,
    pathParams,
    queryParams,
    defaultQueryParams: defaultDashboardQueryParams(),
  });
}

4.1.2 via withQueryParams

We recommend using useQueryParams whenever possible. This method only works with Route as defined from react-router < 5.1.0.

// Dashboard.tsx
import React, { Component } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { Url, withQueryParams, urlBuilder } from '@42.nl/react-url';

import { toDashboard } from './links';

interface DashboardPathParams {
  id: string /* All path params are strings */;
}

interface DashboardQueryParams {
  page: number;
  query: string;
}

/* 
  The default query params are used when no query params are provided
  or when one query param is missing.
*/
export function defaultDashboardQueryParams(): DashboardQueryParams {
  return {
    page: 1,
    query: '',
  };
}

/* 
  By extending RouteComponentProps we get the standard props that
  react-router adds when the component in a route.
*/
interface Props extends RouteComponentProps<DashboardPathParams> {
  queryParams: DashboardQueryParams /* Add the query params to it */;
}

export class Dashboard extends Component<Props> {
  /* 
    You now have access to the query params via the props.
    The `id` is a string which can be found on the match. 
  */

  render() {
    const { queryParams, match } = this.props;
    const { page, query } = queryParams;

    const id = match.params.id;

    return (
      <div>
        <h1>
          Hello {id} You are on page {page} with query {query}.
        </h1>
      </div>
    );
  }
}

/* 
  This is the important part, the Dashboard is wrapped in a
  Higher order Component which provides the `queryParams` prop for use in the Dashboard.
*/
export default withQueryParams(Dashboard, defaultDashboardQueryParams());

export const DASHBOARD_URL = '/dashboard/:id';

export function toDashboard(pathParams: DashboardPathParams, queryParams?: Partial<DashboardQueryParams>): Url {
  return urlBuilder({
    url: DASHBOARD_URL,
    pathParams,
    queryParams,
    defaultQueryParams: defaultDashboardQueryParams(),
  });
}

4.2 Routes

Next you can add the Dashboard to the router like this:

// Routes.tsx

import React from 'react';
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';

import Dashboard, { DASHBOARD_URL, toDashboard } from './Dashboard';

export default function Routes() {
  return (
    <BrowserRouter>
      <div>
        <Link to={toDashboard({ id: 1 })}>Dashboard</Link>

        <Switch>
          <Route exact path={DASHBOARD_URL}>
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </BrowserRouter>
  );
}

Now that we have seen a basic example it is time to show more complex use cases.