@curi/react-dom

GitHub logoGitHub RepoNPM logoNPM Package

About

The @curi/react-dom package provides a number of React components that you can use for rendering your application.

For more information on using Curi with React DOM, please check out the React DOM guide.

Installation

npm install @curi/react-dom

UMD scripts script are also available through Unpkg. You can access the package's exports using window.CuriReactDOM.

API

createRouterComponent

A higher-order component that returns a Router component.

import { createRouterComponent } from '@curi/react-dom';

let router = createRouter(browser, routes);
let Router = createRouterComponent(router);

ReactDOM.render((
  <Router>
    <App />
  </Router>
), node);

Arguments

router

A Curi router.

Return Value

A component that sets routing context data. Any component that relies on routing data must be a descendant of the Router.

children

The Router takes any valid React node (elements, strings, etc.) as its children.

A Link is use for in-app navigation. By default, the component renders an anchor element (<a>). When the rendered element is clicked, instead of reloading the page it will use the router to navigate.

With the Link, instead of providing a URI to navigate to, you specify the name of the route that you want to link to. The pathname of the URI you want the component to link to will be automatically generated for you.

import { Link } from '@curi/react-dom';

<Link name='User' params={{ id: 16 }}>User 16</Link>
// <a href='/user/16'>User 16</a>

The name of the route that the Link should navigate to when it is clicked.

To navigate within the same location, the name can be skipped. This is useful for linking to hashes within the current page.

// Home route is { name: "Home", path: "" }
<Link name="Home">Home</Link>

If the named route (or any of its parents) include path parameters, they must be provided using the params prop.

// User route is { name: 'User', path: '/user/:id' }
<Link name='User' params={{ id: 16 }}>User 16</Link>

The query, hash, and state values for the location to navigate to.

<Link
  name='Products'
  params={{ type: 'vacuums' }}
  hash="iroomba"
  query="volume=loud"
  state={{ owner: "Tom Haverford" }}
>
  DJ Roomba
</Link>

// <a href="products/vacuums?volume=loud#iroomba">
//  DJ Roomba
// </a>

A valid React Node (e.g. a React element, a string, or null).

// a React node
<Link name="Home">
  Home
</Link>

A Link renders an anchor element by default, but this can be changed using the anchor prop. This can be useful for using styled components.

Any additional props attached to the Link will be attached to the element rendered by the Link.

<Link
  name="Home"
  className="home"
>
  Home
</Link>
// <a href="/" class="home">Home</a>

An AsyncLink is similar to a Link, but uses a render-invoked function as its children component.

import { AsyncLink } from '@curi/react-dom';

<AsyncLink name='User' params={{ id: 16 }}>
  {navigating => {
    return navigating
      ? "Navigating to User 16"
      : "Go to User 16"
  }}
</AsyncLink>

<a href='/user/16'>Go to User 16</a>
// click link
<a href='/user/16'>Navigating to User 16</a>
// navigating finishes
<a href='/user/16'>Go to User 16</a>

See Link name

See Link params

See Link hash, query & state

A render-invoked children function that is called with the AsyncLink's navigation state. The navigation state is false to start, true when the AsyncLink is clicked, and false when the the navigation finishes/is cancelled.

<AsyncLink name="User" params={{ id: 1 }}>
  {navigating => (
    <React.Fragment>
      User 1
      {navigating ? <Spinner /> : null}
    </React.Fragment>
  )}
</AsyncLink>

See Link anchor

See Link rest

useResponse

The useResponse hook reads the current response and navigation values from React's context. This will be called every time a new response is emitted.

import { useResponse } from '@curi/react-dom';

function App() {
  let {
    response,
    navigation
  } = useResponse();
  return (
    <ThingThatNeedsResponse
      response={response}
    />
  );
}

useRouter

The useRouter hook returns the router object.

import { useRouter } from '@curi/react-dom';

function App() {
  let router = useRouter();
  // ...
}

useActive

The useActive hook determines if a route is active by comparing a route name (and possibly params) to a response object.

import { useActive, Link } from '@curi/react-dom';

function ActiveLink({
  name,
  params,
  partial,
  children
}) {
  let active = useActive({ name, params, partial });
  return (
    <Link
      name={name}
      params={params}
      className={active ? "active" : ""}
    >
      {children}
    </Link>
  );
}

<ActiveLink name="Home">Home</ActiveLink>

Options

useActive takes a single argument, an options object.

name

The name of the route to compare against the response object.

params

An object containing route parameters. These will be compared against the route params of the response object.

partial

Allows ancestor routes to be considered active when true. Defaults to false.

// response = { name: "User Album", params: { id: "abcde" }}
// where "User Album" is a child route of "User"

useActive({ name: "User" }); // false
useActive({ name: "User", partial: true }); // true

components

The base active check only checks that the route (i.e. pathname) is active. components allows you to check if other components of the location are also active.

useActive({
  name: "Results",
  components: loc => loc.query === "page=3"
});

// active for /results?page=3
// not active for /results?page=1

useConfirm

The useConfirm hook adds and removes a navigation confirmation.

import { useConfirm } from '@curi/react-dom';

useConfirm(confirmation);
// confirmation will be called when the user navigates

useConfirm();
// confirmation will not be called when the user navigates

Arguments

fn

When passed a function, the function will be called when the user navigates and give them the option to confirm or prevent the navigation.

When called with no argument, the existing navigation confirmation will be removed.

useNavigationFocus

The useNavigationFocus hook is used to focus a DOM element after a navigation.

import { useNavigationFocus } from "@curi/react-dom";

function App() {
  let ref = React.createRef(null);
  useNavigationFocus(ref);

  return (
    <main tabIndex={-1} ref={ref}>
      {/* ... */}
    </main>
  );
}

The focused element will have an outline (the exact style varies by browser). You can remove this with CSS by setting outline to "none". This should only be done for non-focusable elements. Setting outline to "none" globally is bad for accessibility.

<main
  ref={ref}
  tabIndex={-1}
  style={{ outline: "none" }}
>
  {/* ... */}
</main>

Options

preventScroll

The default behavior for focusing an element is to scroll to it. If you want to prevent this, set preventScroll to true.

// scrolls
useNavigationFocus(ref);

// does not scroll
useNavigationFocus(ref, { preventScroll: true });

preserve

The default focus behavior is to always focus the element that the ref is attached to. However, if you want to preserve the focus on some other element (e.g. an autofocused element), setting the preserve option to true will stop the ref element from claiming the focus.

This only works when the already-focused element is a child of the ref element. If it is not a child, then the ref element will take the focus.

// claim focus for the <main>
useNavigationFocus(ref)
<main tabIndex={-1} ref={ref}>
  <input autoFocus={true} />
</main>

// preserve focus on the <input>
useNavigationFocus(ref, { preserve: true });
<main tabIndex={-1} ref={ref}>
  <input autoFocus={true} />
</main>

useNavigating

The useNavigating hook is used to determine if the application is currently navigating. It pairs up with router.cancel to enable cancelling asynchronous navigation.

This is only useful for asynchronous routes because with synchronous routes, navigation happens immediately.

import { useNavigating } from "@curi/react-dom";

function CancelNavigation() {
  let cancel = useNavigating();

  return cancel
    ? <button onClick={cancel}>Cancel</button>
    : null;
}

useURL

The useURL hook creates a URL string.

import { useURL } from '@curi/react-dom';

let href = useURL({
  name: "Video",
  params: { id: "jaifeo9" } },
  hash: "comments",
  query: "t=15"
});
// href = "/video/jaifeo9?t=15#comments"

Options

name

The name of the route to generate the location's pathname from. If this is not provided, the generated location's pathname will be an empty string ("");

params

An object of params for the named route.

hash

A hash string for the location.

query

The location's query value.

By default, this is expected to be a string, but if you configure your history object with the query option, this may be something else.

ResponseConsumer

A context consumer component for injecting response values into components. Its primary use case is in class components.

import { ResponseConsumer } from '@curi/react-dom';

class MyComponent {
  render() {
    return (
      <ResponseConsumer>
        {({ response, navigation }) => {
          // pass these props to any components
          // that needs them
          return (
            <ThingThatNeedsResponse
              response={response}
            />
          );
        }}
      </ResponseConsumer>
    );
  }
}

Props

children

A render-invoked function that returns a React element. This function will receive an object with response and navigation properties.

RouterConsumer

A context consumer component for injecting the router into components. Its primary use case is in class components.

import { RouterConsumer } from '@curi/react-dom';

class MyComponent {
  render() {
    return (
      <RouterConsumer>
        {router => {
          return (
            <button onClick={e => {
              login();
              let url = router.url({ name: "Home" });
              router.navigate({ url });
            }}>
              Submit
            </button>
          );
        }}
      </RouterConsumer>
    );
  }
}

Props

children

A render-invoked function that returns a React element. This function will receive the application's router.