React Router v4
React Router v4 isn't like most other routers because it lacks a centralized configuration. Migrating to Curi mostly involves re-centralizing your routes to simplify route management.
Let’s get started with setting up our routes.
With React Router v4,
Routes are defined in components. They are usually grouped together under a
Switch so that only a single route from a group renders. Nested routes are rendered inside of the compnent rendered by the parent
First, we will define the names and paths for our routes.
Each route must have a unique name. A route's name will be used for interacting with it. For example, to navigate to a route, you only have to know its name, not its URL.
The biggest difference between the Curi paths and the React Router paths is that with Curi, you never include a forward slash at the beginning of the path. This means that while the root path for React Router is
'/', the root path for Curi is
Next, we should add our components to each route.
Curi routes can have a
respond property, which is a function that returns an object of properties to merge onto the response that we will be using to render. For this React application, we want a response's
body property to be the React component associated with each route.
With React Router v4, a component's lifecycle methods are used for loading data, code splitting, and other non-rendering tasks. With Curi, routes can have a
resolve function that is called when thee routes matches the new location.
@curi/router route API documentation covers all of the route properties.
Once your routes have been defined, you can move on to creating your Curi router.
With React Router, you create your router by rendering a
Router component. This may be a
MemoryRouter, or a plain
Router that you pass your own
history instance to. The
___Router components create a
history instance for you using props passed to the component.
With Curi, the router is created prior to rendering. It takes a Hickory history function, your routes array, and possibly an options object. Hickory is similar to the
history package used by React Router, but has an API tailored for asynchronous applications.
We will walk through the rendering differences between React Router and Curi by looking at what happens in each when we navigate to the URL with the pathname
React Router matches routes while it renders. It uses the
Router component to listen for location changes. Each time that the location changes, the application re-renders.
Switch will iterate over its children
Routes. The first route,
"/" has an
exact prop, so it only matches when the pathname is
"/". Since it is not, the next
Route will be checked. The next route,
"/inbox" matches the beginning of the pathname
"/inbox/test". It is not an exact match, but that route does not do exact matching, so React Router will render its component,
Inbox has its own
Switch to iterate over. Its first route only matches
"/inbox" exactly, so it moves on to the next route, which has a
message route param. This route matches and stores
Message component will then be rendered, which has access to the
With Curi, we also need to re-render our application every time that the location changes. We will do this by creating a root Curi component by calling the
createRouterComponent function, which comes from the
@curi/react-dom package, and passing it our Curi router. While the name of this component is entirely up to you, we will refer to it as the
Router will setup an observer on the provided router so that it can re-render your application whenever there is a new
Router uses a context provider that makes a response available to other components in the application using the
useResponse hook returns an object with two properties:
responseis the new response object
navigationis an object with additional information about the navigation
The router can also be accessed throughout the application using the
Above, we added
respond functions to each route. The functions set React components as the
body property of responses. We can now use
response.body to render those components.
In the React Router section, we had three components that were rendered:
Message. With Curi, only the most accurately matched route actually matches. That means that for the URL
"Message" route will match, but its parent route,
"Inbox" will not, so
response.body will be the
Message component. Unlike React Router, we don’t render
Inbox because we did not match the
It was mentioned above that there is no need for the
App component with Curi. If you want to have an
App component, you can render it either inside of the
children function or as a parent of your
Router. This can be useful for rendering content that is unrelated to specific routes, like a page header or menu.
App inside of the
children function is necessary if any of the components rendered by the
App are location aware components, since they need to access the Curi router (through React’s context, which the
What about props that you want to send to your route components? Pass them to the
Body component that you render. Props can be passed individually, but passing the whole
response object is recommended.
React Router provides a
withRouter higher-order component that will inject router props into the wrapped component.
Curi provides similar functionality with the
The best way to get router data with Curi is to use the
At this point, hopefully you are comfortable with migrating from React Router v4 to Curi. If there are any concepts not covered here that you think should be, please feel free to open up an issue on GitHub.