Declarative routing for React

Related tags

react-router
Overview

react-router

React Router

Declarative routing for React

Docs

View the docs here

Migrating from 2.x/3.x?

3.x docs

2.x docs

Packages

This repository is a monorepo that we manage using Lerna. That means that we actually publish several packages to npm from the same codebase, including:

Package Version Docs Description
react-router npm The core of React Router
react-router-dom npm DOM bindings for React Router
react-router-native npm React Native bindings for React Router
react-router-config npm Static route config helpers

Redux users: The react-router-redux package is now deprecated. See Redux Integration for a better approach.

Changes

Detailed release notes for a given version can be found on our releases page.

For change notes prior to version 4, please see the CHANGES.md file.

Funding

You may provide financial support for this project by donating via Open Collective, attending one of our workshops, or purchasing one of our online courses. Thank you for your support!

About

react-router is developed and maintained by React Training and many amazing contributors. If you're interested in learning more about what React can do for your company, please get in touch!

Issues
  • Server rendering

    Server rendering

    Route.spec.js contains a commented out test for server rendering but it seems, server rendering would at least require exposing findMatches in the main module.

    Any plans for reintroducing server rendering support?

    opened by simenbrekken 157
  • Rewrite, version 1.0

    Rewrite, version 1.0

    NOTE: DO NOT MERGE YET

    This PR is a complete rewrite of the router with the following goals in mind:

    • simpler top-level API with less boilerplate
    • async route config and/or component loading (better support for code splitting in large apps)
    • simpler API for server-side rendering
    • more React-like <RouteHandler> API
    • easier data fetching API

    ... and a bunch of other stuff that we've learned from various issues over the past year.

    Here's a summary of the various things you can do:

    Top-level API

    var { createRouter, Route } = require('react-router');
    
    var Router = createRouter(
      <Route component={App}>
        <Route name="home" component={Home}/>
      </Route>
    );
    
    // The minimal client-side API requires you to pass a history object to your router.
    var BrowserHistory = require('react-router/lib/BrowserHistory');
    React.render(<Router history={BrowserHistory}/>, document.body);
    
    // On the server, you need to run the request path through the router
    // first to figure out what props it needs. This also works well in testing.
    Router.match('/the/path', function (error, props) {
      React.renderToString(<Router {...props}/>);
    });
    

    The props arg here contains 4 properties:

    • location: the current Location (see below)
    • branch: an array of the routes that are currently active
    • params: the URL params
    • components: an array of components (classes) that are going to be rendered to the page (see below for component loading)

    The branch and components are particularly useful for fetching data, so you could do something like this:

    BrowserHistory.listen(function (location) {
      Router.match(location, function (error, props) {
        // Fetch data based on what route you're in.
        fetchData(props.branch, function (data) {
          // Use higher-order components to wrap the ones that we're gonna render to the page.
          wrapComponentsWithData(props.components, data);
          React.render(<Router {...props}/>, document.body);
        });
      });
    });
    

    Inside your App component (or any component in the hierarchy) you use this.props.children instead of <RouteHandler> to render your child route handler. This eliminates the need for <RouteHandler>, context hacks, and <DefaultRoute> since you can now choose to render something else by just checking this.props.children for truthiness.

    <NotFoundRoute> has also been removed in favor of just using <Route path="*">, which does the exact same thing.

    Non-JSX Config

    You can provide your route configuration using plain JavaScript objects; no JSX required. In fact, all we do is just strip the props from your JSX elements under the hood to get plain objects from them. So JSX is purely sugar API.

    var Router = createRouter(
      {
        component: App,
        childRoutes: [{
          name: 'home',
          component: Home
        }]
      }
    );
    

    Note the use of childRoutes instead of children above. If you need to load more route config asynchronously, you can provide a getChildRoutes(callback) method. For example, if you were using webpack's code splitting feature you could do:

    var Router = createRouter(
      {
        component: App,
        getChildRoutes(callback) {
          require.ensure([ './HomeRoute' ], function (require) {
            callback(null, [ require('./HomeRoute') ]); // args are error, childRoutes
          }
        }
      }
    );
    

    Which brings me to my next point ...

    Gradual Path Matching

    Since we want to be able to load route config on-demand, we can no longer match the deepest route first. Instead, we start at the top of the route hierarchy and traverse downwards until the entire path is consumed by a branch of routes. This works fine in most cases, but it makes it difficult for us to nest absolute paths, obviously.

    One solution that @ryanflorence proposed was to let parent routes essentially specify a function that would return true or false depending on whether or not that route thought it could match the path in some grandchild. So, e.g. you would have something like:

    var Router = createRouter(
      {
        path: '/home',
        component: Home,
        childRouteCanMatch(path) {
          return (/^\/users\/\d+$/).test(path);
        },
    
        // keep in mind, these may be loaded asynchronously
        childRoutes: [{
          path: '/users/:userID',
          component: UserProfile
        }]
      }
    );
    

    Now, if the path were something like /users/5 the router would know that it should load the child routes of Home because one of them probably matches the path. This hasn't been implemented yet, but I thought I'd mention it here for discussion's sake.

    Async Component Loading

    Along with on-demand loading of route config, you can also easily load components when they are needed.

    var Router = createRouter(
      {
        path: '/home',
        getComponents(callback) {
          require.ensure([ './Home' ], function (require) {
            callback(null, require('./Home')); // args are error, component(s)
          }
        }
      }
    );
    

    Rendering Multiple Components

    Routes may render a single component (most common) or multiple. Similar to ReactChildren, if components is a single component, this.props.children will be a single element. In order to render multiple components, components should be an object that is keyed with the name of a prop to use for that element.

    var App = React.createClass({
      render() {
        var { header, sidebar } = this.props;
        // ...
      }
    });
    
    var Router = createRouter(
      {
        path: '/home',
        component: App,
        childRoutes: [{
          path: 'news',
          components: { header: Header, sidebar: Sidebar }
        }]
      }
    );
    

    Note: When rendering multiple child components, this.props.children is null. Also, arrays as children are not allowed.

    Props

    Aside from children, route components also get a few other props:

    • location: the current Location (see below)
    • params: the URL params
    • route: the route object that is rendering that component

    Error/Update Handling

    The router also accepts onError and onUpdate callbacks that are called when there are errors or when the DOM is updated.

    History/Location API

    Everything that used to be named *Location is now called *History. A history object is a thing that emits Location objects as the user navigates around the page. A Location object is just a container for the path and the navigationType (i.e. push, replace, or pop).

    History objects are also much more powerful now. All have a go(n) implementation, and HTML5History and History (used mainly for testing) have reliable canGo(n) implementations.

    There is also a NativeHistory implementation that should work on React Native, tho it's a little tricky to get it working ATM.

    Transition Hooks

    The willTransitionTo and willTransitionFrom transition hooks have been removed in favor of more fine-grained hooks at both the route and component level. The transition hook signatures are now:

    • route.onLeave(router, nextState)
    • route.onEnter(router, nextState)

    Transition hooks still run from the leaf of the branch we're leaving, up to the common parent route, and back down to the leaf of the branch we're entering, in that order. Additionally, component instances may register hook functions that can be used to observe and/or prevent transitions when they need to using the new Transition mixin. Component instance-level hooks run before route hooks.

    var { Transition } = require('react-router');
    
    var MyComponent = React.createClass({
      mixins: [ Transition ],
      transitionHook(router) {
        if (this.refs.textInput.getValue() !== '' && prompt('Are you sure?'))
          router.cancelTransition();
      },
      componentDidMount() {
        this.addTransitionHook(this.transitionHook);
      },
      componentWillUnmount() {
        this.removeTransitionHook(this.transitionHook);
      },
      render() {
        return (
          <div>
            <input ref="textInput" type="text"/>
          </div>
        );
      }
    });
    

    Anyway, apologies for the long-winded PR, but there's a lot of stuff here! Please keep comments small and scoped to what we're doing here. I'd hate for this to turn into a huge thread :P

    Edit: Added data-loading example. Edit: Added transition hooks. Edit: Added props for named children, disallow arrays. Edit: Added addTransitionHook/removeTransitionHook API. Edit: Renamed Router.run => Router.match Edit: Removed static transition hooks

    Stuff we still need:

    Ok. Stuff we still need here:

    • [ ] Support absolute paths inside nested UI somehow in new path matching algorithm
    • [x] ~~Move routerWillLeave hook to instance lifecycle method instead of static~~ Add component-level API for observing/preventing transitions
    • [x] Add back scroll history support (@gaearon can you help w/ this?)
    • [ ] Maybe remove canGo(n) support (@taurose can you help determine if the current impl. is legit or not? if not, let's just remove it)

    COME ON! LET'S GET THIS MERGED AND SHIP 1.0!!!!

    opened by mjackson 141
  • RFC: Relative Links and Routes

    RFC: Relative Links and Routes

    We intend to ship Relative Routes and Relative Links soon. I'd like to hear people's comments on something I'm not totally sure about yet.

    What are Relative Links and Routes?

    Instead of <Route path={match.path + '/more/stuff'}/> you could simply do <Route path="more/stuff"/> and Router will use the lack of / at the start of your path as a hint that you want to just use whatever path is above you. Relative!

    Same with links. Instead of <Link to={match.url + '/more/stuff'}/> you can just do <Link to="more/stuff"/>.

    The Problem

    Going "down" as shown in the quick example up there is easy. But we're not sure what ".." should mean. There are two options for what it means: go up a URL segment, or go up a matched route.

    Go up a URL segment

    With plain anchors tags, .. means "up a URL segment". Given the following URL, an anchor tag with the following HREFs results in the following URLs:

    /clients/invoice/123
    

    href | url -----|----- payments | /clients/invoice/123/payments | /clients/invoice/123 . | /clients/invoice/123 .. | /clients/invoice ../ | /clients/invoice ../.. | /clients ../../ | /clients

    (As far as I can tell, feel free to double check!)

    So I think everybody's intuition around this is to just do exactly that and be done with it. Ship it.

    However, I have this gut instinct that our intuition right now might be keeping us from a better meaning of ".." in a React Router app?

    Go up a matched Route

    Maybe your app is something like this:

      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/clients" render={() => (
          <Clients>
            <Switch>
              <Route exact path="." component={ClientList}/>
              <Route path="invoice/:invoiceId" component={Invoice}/>
            </Switch>
          </Clients>
        )}/>
      </Switch>
    

    Maybe we want ".." to mean "go up a matched route" rather than "go up some url segments".

    So now the "relative" portion of the Link's to prop is the parent Route's path, not the current location.

    to prop | link's url -----|----- .. | /clients ../.. | /

    Notice .. doesn't go to "invoice" because that's not a route that will ever match.

    Pros

    • When you change a parent Route's path prop, the relative links below don't need to be updated
    • You can't link to something that doesn't have UI (probably, see cons*)

    Cons

    • *Since any ol' route can match a location w/o a relationship with other Route's that match, a Link in one place can potentially have a completely different href than a link somewhere else--even though they have the same to prop 😬. It all depends on the Route's path the Link is rendered within.
    • It's against most people's intuition

    What do you think?

    opened by ryanflorence 116
  • [added] Router.renderRoutesToString

    [added] Router.renderRoutesToString

    This PR allows the path to be given to as a prop.

    <Routes initialPath="/some/path"> ... </Routes>
    

    This only works server side. This patch also stops the URLStore and RoutesStore being started as componentWillMount is called but componentWillUnmount isn't call on server side. This would lead to a memory leak and potential async issue when multiple pages are being rendered at once.

    When rendering on server side you should always make a new instance of <Routes> so if multiple pages are being rendered they don't change the routes in another page.

    var App = React.createClass({
      render: function(){
        return <Routes initialPath={this.props.initialPath} location="history"> ... </Routes>
      }
    });
    
    //server side
    React.renderComponentToString(<App initialPath="/some/path" />);
    
    //client side
    React.renderCompoent(<App />, domelement);
    
    opened by karlmikko 108
  • how to reload a route?

    how to reload a route?

    How do i tell react-router to reload current route?

    opened by pdeva 108
  • Proposal: Replace AsyncState with getAsyncProps

    Proposal: Replace AsyncState with getAsyncProps

    Edit: Please read my updated proposal as well

    I'd like to propose adding two new transition hooks, didTransitionTo and didTransitionFrom that are designed to replace the AsyncState mixin. Currently, AsyncState has the following quirks/limitations:

    • It keeps data in this.state, but data is passed passed to children through props in render
    • It's a mixin but it was only ever intended to be used in route handler components, so users may be inclined to use it in other components (which we don't support). Also, it means that users need to declare the mixin

    The goals for these two new transition hooks are:

    • Keep data in props, where it belongs. this.state should be used for UI state
    • Keep the ability for components to subscribe to changes in data, but also have a way to let components know that data only needs to be fetched once (for server rendering)
    • Keep the ability for components to fetch data in parallel
    • More clearly indicate that data fetching behavior belongs in route handlers, and not other components and eliminate the need for users to declare a mixin in order to use it

    I believe the following API satisfies all of the above requirements. Feedback is welcome.

    var User = React.createClass({
    
      statics: {
    
        // This hook is called after the transition has been validated by all
        // willTransition* hooks. The setProps argument is a function that
        // can be used to set props ad hoc (like AsyncState's setState).
        didTransitionTo: function (params, query, singleRun, setProps) {
          // If you have an immediate value, use it.
          setProps({ user: UserStore.getUserByID(params.userID) });
    
          // If we're not on the server, subscribe to changes in the data.
          if (!singleRun) {
            this.userListener = function () {
              setProps({ user: UserStore.getUserByID(params.userID) });
            };
    
            UserStore.addChangeListener(this.userListener);
          }
    
          // Or, ignore setProps entirely and return a hash of values that should
          // be used as props. Values may be immediate or promises. As they
          // resolve, props are updated.
          return {
            user: fetchUser(params.userID)
          };
        },
    
        // This hook is called after the transition has been validated by all
        // willTransition* hooks.
        didTransitionFrom: function () {
          UserStore.removeChangeListener(this.userListener);
        }
    
      },
    
      // The render method needs to be resilient to the fact that props
      // may not yet be loaded.
      render: function () {
        var user = this.props.user;
        var name = user == null ? 'anonymous' : user.name;
    
        return <div className="user-component">Hello {name}!</div>;
      }
    
    });
    

    Note that, although this API looks similar to the willTransition* API, it has two key differences:

    • handlers are run in parallel, not in sequence, so all data can be fetched at the same time
    • the resolution of these handlers does not block the transition from happening

    Thanks to @rpflorence for giving me feedback and helping me think through this API earlier today!

    Edit: Updated example code to make setProps the last (optional) argument to didTransitionTo.

    feature 
    opened by mjackson 107
  • v2 Roadmap

    v2 Roadmap

    This might not be the best way to manage this (one gigantic issue), but @mjackson and I are a solid 50% done with all of this anyway, so I'm not too concerned.

    @taion you'll likely have some questions since this affects a lot of what you're trying to do, please chat me up on discord before we clog up this issue with back-and-forth conversation :)

    Router 2.0 Roadmap

    TOC

    Motivations for the following API changes are all about cleaning up and clarifying the coupling between React Router and History; this generally translates to "You won't need to know anything about History anymore."

    • Learning the router is complicated by History, you have to learn both APIs and the line between them is unclear. This affects end users trying to use the libraries together as well as contributors (for example duplication of docs is also a problem).
    • We have some rough edges around ingration with libraries like React native, Redux, Relay, and our own AsyncProps.
    • React 15 is only going to allow components to export only one object to "context" (we only want one anyway)

    The following issues should help address these concerns.

    Note about upgrading

    All v1.0.0 APIs will continue to work in v2.0.0. An app using only public API should be able to drop in v2.0.0 and just get warnings. Old API will be removed in 3.0.0. If you update your code and no longer get warnings, you should be able to upgrade to 3.0 w/o trouble.

    Ship History 2.0

    It's really just removing deprecated API. The rest of these items all kind of depend on it though.

    Refactor route matching out of useRoutes and into match

    Background

    Currently we wrap a history with useRoutes so it is now aware of routes and performs the match against them. This changes the signature and timing of listen (making it async) causing difficulty when integrating or using alongside libraries like redux and react native.

    Additionally, navigating outside of components (like in flux and redux) is complicated by Router wrapping the history provided as a prop.

    Goals

    • Remove need for listenRoutes to integrate with other libs
    • Make navigating outside of components simpler for redux/flux etc.
    • Not require apps to wrap their singleton history in things like useQueries in order to navigate outside of components
    • apps can still learn about History and add behavior if they choose, (custom queryString parsing, etc.) and Router should not touch the history provided

    Upgrading

    ////////////////////////////////////////////////////////////////////////////////
    // Rendering
    // v1.0.0
    import createBrowserHistory from 'history/lib/createBrowserHistory'
    render(<Router history={createBrowserHistory()}/>, el)
    
    // v2.0.0
    import { browserHistory } from 'react-router'
    render(<Router history={browserHistory}/>, el)
    
    ////////////////////////////////////////////////////////////////////////////////
    // Navigating outside of components
    
    // v1.0.0
    // probably exported from a module somehwere like this
    import createBrowserHistory from 'history/lib/createBrowserHistory'
    import useQueries from 'history/lib/useQueries'
    const createHistory = useQueries(createBrowserHistory)
    export default createHistory()
    // and then used in an action or somehwere
    import appHistory from './appHistory'
    appHistory.push(...)
    
    // v2.0.0
    // React Router exports a singleton
    import { browserHistory } from 'react-router'
    browserHistory.push(...)
    

    Tasks

    While the nitty gritty won't be this simple, this is what will probably need to happen:

    • remove useRoutes and move all route matching to match
    • use match inside of Router instead of wrapping the history provided in anything (don't alter history)
    • create hashHistory and browserHistory singletons, exported from index.js
    • remove default to hashHistory and require devs to provide one, should help with people not understanding that there's a better option, and allow devs to decrease the bundle size of their app

    Export only router to context

    Background

    Right now we put history, location, and route (sometimes) on context, we also pass a bag of props to route components. Turns out there's some overlap between them. We're tempted to add more to context, and add more to props because the line and purpose between them isn't clear.

    React Router continues to strive to be just one library in a wonderful ecosystem of other libraries, prescribing strategies for data flow in an app is not our goal. We will put only what we absolutely need in context (which can be summed up with "what does Link need?). Everything else will go to route components as props. The opinions of the app can take over from there.

    Context was recently documented, so we no longer need the mixins to hide the context API. It's up to the app to decide if it wants to use context directly or continue to hide it with mixins or higher order components.

    Also, react 15 or 16 will only allow one contextType. We've been talking about only have one context type for a while. Now is the time.

    Finally, in the global effort to make History an implementation detail, we need to provide something else to navigate around in components.

    Goals

    • Make separation between what is on context v. route props clear, and remove overlap
    • Let apps decide how to get props the router gives them down the render tree
    • Remove need to learn History API

    Tasks

    • Deprecate all items on context: history, location, route

    • Add context.router that looks like this:

      router: shape({
        push: func,
        replace: func,
        isActive: func,
        addRouteLeaveHook: func
      })
      
    • Pass router as a prop to route components

    • Deprecate all mixins

    • Deprecate passing history to route components

    • proxy push/replace/isActive/addRouteLeaveHook to underlying history (so integration with a custom history will work)

    • automatically remove route leave hooks since we should know everything we need to know, so devs don't have to and there's no reason to leave them hanging around.

    Upgrading

    History methods

    In all cases where you once had a history for navigation, you now have a router with different methods.

    // v1.0.0
    history.pushState(state, path, query)
    history.replaceState(state, path, query)
    
    // v2.0.0
    router.push(path)
    router.push({ path, query, state }) // new "location descriptor"
    
    router.replace(path)
    router.replace({ path, query, state }) // new "location descriptor"
    

    Navigating in route components

    // v1.0.0
    class RouteComponent extends React.Component {
      someHandler() {
        this.props.history.pushState(...)
      }
    }
    
    // v2.0.0
    class RouteComponent extends React.Component {
      someHandler() {
        this.props.router.push(...)
      }
    }
    

    Navigating inside deeply nested components

    // v1.0.0
    const DeepComponent = React.createClass({
      mixins: [ History ],
    
      someHandler() {
        this.history.pushState(...)
      }
    }
    
    // v2.0.0
    // You have a couple options:
    // Use context directly (recommended)
    const DeepComponent = React.createClass({
      contextTypes: {
        router: object.isRequired
      },
    
      someHandler() {
        this.context.router.push(...)
      }
    }
    
    // create your own mixin:
    const RouterMixin = {
      contextTypes: {
        router: object.isRequired
      },
      componentWillMount() {
        this.router = this.context.router
      }
    }
    
    const DeepComponent = React.createClass({
      mixins: [ RouterMixin ],
      someHandler() {
        this.history.pushState(...)
      }
    }
    
    // use the singleton history you are using when the router was rendered,
    import { browserHistory } from 'react-router'
    
    const DeepComponent = React.createClass({
      someHandler() {
        browserHistory.push(...)
      }
    }
    

    Lifecycle Mixin with route components

    // v1.0.0
    const RouteComponent = React.createClass({
      mixins: [ Lifecycle ],
      routerWillLeave() {
        // ...
      }
    })
    
    // v2.0.0
    const RouteComponent = React.createClass({
      componentDidMount() {
        const { router, route } = this.props
        router.addRouteLeaveHook(route, this.routerWillLeave)
      }
    })
    
    // or make your own mixin, check it out in the next section
    

    Lifecycle Mixin with deep, non-route components

    // v1.0.0
    const DeepComponent = React.createClass({
      mixins: [ Lifecycle ],
      routerWillLeave() {
        // do stuff
      }
    })
    
    // v2.0.0
    // you have a couple of options
    // first you can put the route on context in the route component
    const RouteComponent = React.createClass({
      childContextTypes: {
        route: object
      },
    
      getChildContext() {
        return { route: this.props.route }
      }
    })
    
    // and then access it on your deep component
    const DeepComponent = React.createClass({
      contextTypes: {
        route: object.isRequired,
        router: objec.isRequired
      },
    
      componentDidMount() {
        const { router, route } = this.context
        router.addRouteLeaveHook(route, this.routerWillLeave)
      }
    })
    
    // or make your own mixin that will work for both route components and
    // deep components alike (as long as your route component puts `route`
    // on context
    const Lifecycle = {
      contextTypes: {
        route: object.isRequired,
        router: objec.isRequired
      },
    
      componentDidMount() {
        const router = this.context.router
        const route = this.props.route || this.context.route
        router.addRouteLeaveHook(route, this.routerWillLeave)
      }
    }
    

    Add render prop to Router, remove RoutingContext prop

    Background

    The functional composition of history is awesome, but we also need this kind of composition for React Router when it's time to render. While we can add some behavior into history we lack the necessary lifecycle hooks that components give us. Integrations also need all of the routing information in aggregate (like all the components and routes).

    Our current workaround is the RoutingContext prop, but that only lets us add one level of behavior. Consider an app that was built with Async Props, but now wants to iterate to using Relay, as well as add a new scroll restoring behavior. If each of these components used the RoutingContext prop API, they would all render a RoutingContext and therefore can't be used together.

    Goals

    • Allow integration for middleware components that need lifecycle hooks and the aggregate routing information
    • Allow multiple levels of behavior, not just one

    Upgrading

    // v1.0.0
    render(<Router RoutingContext={AsyncProps}/>, el)
    
    // v2.0.0
    render((
      <Router render={(props) => (
        <AsyncProps {...props} render={(props) => (
          <RoutingContext {...props} />
        )}/>
      )}/>
    ), el)
    
    // While that's more code, now we can do this:
    render((
      <Router render={(props) => (
        <AsyncProps {...props} render={(props) => (
          <RelayRoutes {...props} render={(props) => (
            <ScrollRestorer {...props} render={(props) => (
              <RoutingContext {...props} />
            )}/>
          )}/>
        )}/>
      )}/>
    ), el)
    

    Tasks

    • Remove RoutingContext prop, no need for deprecation warnings, it's undocumented and everybody we've told to try it got an earful of "we aren't sure about this thing yet"
    • Add render prop to Router
    • Add a default prop that just renders a RoutingContext
    • Write a document about how to write a middleware component (should continue to send down the props in a method called render

    Holy smokes that looks like a lot, it's really not too much, and we're feeling really good about it all.

    opened by ryanflorence 97
  • Allow transition hooks access to a context object you can specify when you create the router.

    Allow transition hooks access to a context object you can specify when you create the router.

    I've been trying to make an authentication mixin that can access the state in one of my flux stores but am not using singletons that I can make available to the static methods. Would it be alright to pass a context object through to the static willTransition hook methods to allow them access to arbitrary services you might need?

        var context = {...}
        Router.create({routes: routes, transitionContext: context})
    
        statics: {
          willTransitionTo: function(transition) {
             var loginState = transition.context.getStore(LoginStore).getState();
          }
        }
    
    opened by bobpace 96
  • Server rendering dynamic routes

    Server rendering dynamic routes

    I use server side rendering with some code splitting routes. It looks like OK on my server side with shim require.ensure. But I get the following warning on my client side:

    Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
     (client) ctid=".bqth22sav4"><noscript data-reacti
     (server) ctid=".bqth22sav4"><div data-reactid=
    

    Here is the main part of my client side codes:

    
    const store = createStore(getInitialState());
    const history = createHistory();
    const { pathname, search } = window.location;
    const location = createLocation(pathname + search);
    
    match({ routes, location }, (err, redirectLocation, renderProps) => {
        render(
            <Provider store={store}>
                <Router
                    {...renderProps}
                    history={history}
                />
            </Provider>,
            document.getElementById('mount')
        );
    });
    

    Regards.

    feature 
    opened by Cap32 95
  • React Native

    React Native

    Just tracking react native thoughts here. My assumptions are probably all wrong since 1) I don't know much about native dev and 2) I've spent 5 minutes with react native but:

    1. Looks like a component is mounted as the "top level" thing, the router listens to a location and then renders an app, so the basic usage is probably going to be slightly different, your top level component has route definitions and gets a url passed in as a prop or something.
    2. We need some sort of iOS Location and eventually an Android location, it'll probably be stored in memory and persisted to some sort of localStorage equivalent. When the app boots we look at the URI requesting the launch first, and then the localStorage (whatever it really is) second.

    Again, I have no idea what I'm talking about yet. Β―(ΒΊ_o)/Β―

    opened by ryanflorence 95
  • feat: warn for leaf routes with no element

    feat: warn for leaf routes with no element

    See https://github.com/remix-run/react-router/issues/8145

    opened by jacob-ebey 0
  • [Docs V5] Animated transitions example is broken

    [Docs V5] Animated transitions example is broken

    Version

    Docs for v5

    Test Case

    https://reactrouter.com/web/example/animated-transitions. edit: also on https://v5.reactrouter.com/web/example/animated-transitions

    Steps to reproduce

    Go to the URL above

    Expected Behavior

    The codesandbox embed loads correctly

    Actual Behavior

    The codesandbox embed displays the following error message:

    Something went wrong while fetching the sandbox: file not found at: https://raw.githubusercontent.com/ReactTraining/react-router/master/packages/react-router-dom/examples/Animation/styles.css

    opened by Apollinaire 0
  • Does v6 drop support for class components?

    Does v6 drop support for class components?

    First of all, thank you for making react-router available to the world :)

    I'm not sure if this is the best place to ask about this but given that this is monitored by the maintainers I figured I could put my question here.

    My question is around the fact that based on the currently available documentation for v6 (the migration/upgrade guide) react-router v6 seems to drop out-of-the-box support for class components and all the codebases that already have plenty of them (like ours) due to the following changes:

    1. Dropping support for the render prop in the Route component, which we are using with react-router v5 to pass params to the component (through props.match.params) of the route.

    2. Replacing the use of History (which was passed as a prop to our components automatically in v5) with the new NavigateFunction and the fact that it's only available through the useNavigate hook which of course is not accessible to class components.

    Could someone shed the light on this and the future of react-router for all of us who are using class components and will most likely stick with using them for the foreseeable future?

    Thanks in advance.

    opened by AbrahamLopez10 4
  • Warning for leaf routes w/ no element

    Warning for leaf routes w/ no element

    We should warn when the leaf route has no element prop. In this case, the element would default to an <Outlet> that renders null, which can be confusing.

    let routes = (
      <Routes>
        {/* When the URL is /layout, this route will match but won't render anything! */}
        <Route path="layout">
          <Route path="page" element={...} />
        </Route>
      </Routes>
    );
    
    opened by mjackson 0
  • Allow path on index routes

    Allow path on index routes

    We should allow index routes to have a path. This eliminates the need to nest them inside their parent route.

    e.g. this should be a totally valid route config:

    let routes = (
      <Routes>
        <Route path="layout" element={...}>
          <Route path="page" element={...} />
        </Route>
        <Route path="layout" index element={...} />
      </Routes>
    );
    

    Implementation

    I don't think any implementation actually needs to change here, just the IndexRouteProps declaration. But we should write a test or two just to be sure.

    opened by mjackson 0
  • Rank index routes higher than layouts

    Rank index routes higher than layouts

    Index routes should rank higher than sibling layout routes with the same path.

    let routes = (
      <Routes>
        <Route path="layout" element={...}>
          <Route path="page" element={...} />
        </Route>
    
        {/* When the URL is /layout, this route should match because it is more specific */}
        <Route path="layout" index element={...} />
      </Routes>
    );
    
    opened by mjackson 1
  • [v6] [Bug] Link is wrong on rerenders when using a basename

    [v6] [Bug] Link is wrong on rerenders when using a basename

    Version

    6.0.0-beta.6

    Test Case

    https://codesandbox.io/s/react-router-v6-link-w-basename-bug-report-bhyn8?file=/index.js

    Go to /abc/topics/1 in the sandbox to see the issue.

    Steps to reproduce

    Rerender a Link without remounting it inside a Router with a basename. The link must be using a string for the to param. If it uses the object syntax it will work. No idea why those are different. There may be more, but this is all I've narrowed it down to at the moment.

    Expected Behavior

    The link renders the given to relative to the current basename. rerenders don't change the link's href.

    Actual Behavior

    Basically, every rerender the link adds the current basename onto itself, but it already has a basename, so it just grows indefinitely. E..g with basename abc render 1: /abc/x/1 render 2: /abc/abc/x/1 render 3: /abc/abc/abc/x/1 etc...

    opened by AHBruns 1
  • [V6] [Feature] Getting `usePrompt` and `useBlocker` back in the router

    [V6] [Feature] Getting `usePrompt` and `useBlocker` back in the router

    I think in general most people won't be able to upgrade to v6 since in the latest beta usePrompt and useBlocker are removed.

    Most apps rely on the usePrompt or Prompt to prevent navigation in case the user has unsaved changes (aka the form is dirty).

    With this issue maybe we can have some feedback on why they (usePrompt, Prompt) were removed (they worked fine in the previous beta version v6.0.0-beta.6) and what makes them problematic, what's the outlook for getting them back in the router and potentially userland solutions to this problem.

    opened by callmeberzerker 1
  • chore(ci): do all the docs updating in website action

    chore(ci): do all the docs updating in website action

    this makes it way easier to try it again if it fails

    opened by mcansh 0
  • [Bug]: useHref updates result from useResolvedPath

    [Bug]: useHref updates result from useResolvedPath

    What version of React Router are you using?

    v6.0.0-beta.6

    Steps to Reproduce

    I have the following sample:

    return <Router basename="/_basePath">
      //...
      <Link to="/page1"/>
      //... 
    </Router>;
    

    Expected Behavior

    I expected the following output:

    <a href="/_basePath/page1"></a>
    

    Actual Behavior

    In some cases I get the following result as the Link component is rendered multiple times:

    <a href="/_basePath/_basePath/_basePath/page1"></a>
    

    The issue is that useHref is overwriting the reference which is returned from useResolvedPath and prepend the basepath multiple times: https://github.com/remix-run/react-router/blob/f41e3c95eb848b292244e1e1cb1eb2a6cc3f7525/packages/react-router/index.tsx#L402

    opened by fxOne 0
Releases(v6.0.0-beta.7)
  • v6.0.0-beta.7(Oct 15, 2021)

    In this release we made a small but significant change to how <Link to=".."> works. This is going to help out a lot if you were trying to use links in a * route.

    We have also backed out our blocking/prompt APIs for the stable v6 release. We will revisit this post 6.0 when we have a little more time to get it right.

    ✨ Features

    The major change in this release could also be classified as a bugfix or a breaking change, depending on how you look at it. We essentialy altered the way <Link to=".."> works. See #8086 for the motivation behind this change.

    You'll probably want to reread the section in the v5 => v6 migration guide about <Link to> values (it has been updated), but it basically boils down to this: any leading .. segment in a <Link to> value traverses "up" one route and builds upon that route's path instead of just removing one URL segment. This feature really completes the story of relative routes and links.

    We could consider this a bugfix, since this is how it was always intended to work in the first place. Without it, you'd have a difficult time linking predictably in * routes because your <a href> would be different depending on the number of segments in the current URL.

    The reason this could also be considered a breaking change is that .. now works slightly differently in <Link to> than it would in <a href>. When you have <a href=".."> it operates on the URL pathname, removing one segment of the current URL. However, since many routes really only match a single segment of the URL, there is often no difference between <Link to=".."> and <a href="..">.

    πŸ’” Breaking Changes

    • We removed useBlocker(), usePrompt(), and <Prompt> for now. We will revisit these post 6.0 when we have more time to get it right. But we don't want it to block (see what I did there) the release of all the other awesome stuff we've got in v6.

    πŸ›  Roadmap

    We anticipate this will be the last beta release before v6 stable next week. Please give it a shot and let us know how it goes!

    πŸ‘ Upgrading

    If you're thinking about upgrading to v6, I published a few notes this past week that may help you:

    Both of those posts contain steps you can take today in your v5 app without upgrading to v6.

    We are also developing a backwards compat lib that should help some of you upgrade from v5 to v6. We'll post more about this when it's ready.

    πŸ’» Installing

    Development for v6 has switched from dev to the main branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    
    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-beta.6(Oct 7, 2021)

    No big enhancements in this release, just squashing bugs and writing lots of tests! Also, we are hard at work on cranking out examples for v6. See the end of this post for an update on our roadmap between here and v6 stable.

    🧰 Examples

    We have begun creating some examples for v6 that we hope will help developers make effective use of all the new features we have. So far, we have examples for the following:

    • Basic Example – A basic client-side app for v6 showing how to use nested routes, layouts, links, and the new <Outlet> API
    • Auth Example – Demonstrates an authentication flow including using the new useNavigate() hook, the <Navigate> element, and location.state
    • Search Params Example – Demonstrates how to build a simple search form that uses the new useSearchParams() hook
    • SSR Example – A server-rendered app that uses <StaticRouter> on the server and uses a <BrowserRouter> with ReactDOM.hydrate() on the client

    Each example includes a button in the README that allows you to instantly launch a running instance on StackBlitz that you can play with. We hope you enjoy exploring!

    πŸ› Bugfixes

    • Make <NavLink> match only whole URL segments instead of pieces. This means that <NavLink to="/home/users"> will still be active at /home/users, but not at /home/users2. See #7523
    • Makes "layout routes" (routes with no path) never match unless one of their children do. See #8085
    • Fixes a route matching regression with splat routes that was introduced in beta.5. See #8072 and #8109
    • Fixes matching a nested splat route. See af7d038e
    • Provide all parent route params to descendant <Routes>. This reverses a decision that we made in beta.5 to remove them. See #8073

    πŸ’” Breaking Changes

    • Splats in route paths (*) match only after a / in the URL. This means that <Route path="files*"> will always match as if it were <Route path="files/*">. The router will issue a warning if your route path ends with * but not /*

    πŸ›  Roadmap

    We are very close to a stable release! The last big code changes we need to make are:

    • Fixing "linking up". Currently a <Link to=".."> operates on the URL pathname. However, this makes it difficult to link to the parent route when you're in a splat route. See #8086. This will be a breaking change.
    • We are going to remove useBlocker() and <Prompt> in our initial v6 release, with plans to revisit them and possibly add them back at some point in the future. I still need to write up something here that explains our rationale. This will also be a breaking change.
    • We are going to add some animation primitives (see https://github.com/remix-run/react-router/discussions/8008). The <Routes location> prop will be in v6, but it isn't ideal for animation.

    πŸ’» Installing

    Development for v6 is chugging along on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    
    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-beta.5(Sep 25, 2021)

    This week's release adds some much-needed polish to a few niche features of the router: splat routes (a route that uses a * path) and basenames. It also adds a renderMatches API that completes the story for those of you who may have been using react-router-config in v4 and v5.

    πŸ› Bugfixes

    • A * in a child route path matches after a slash following its parent route path. This fixes some situations where the * was overly greedy (see #7972)
    • Resolution of <Link to="."> and useResolvedPath(".") values are fixed in splat routes. Previously these resolved relative to the parent route's path. They now resolve relative to the path of the route that rendered them.

    ✨ Enhancements

    This release makes it easier to work with apps that have multiple entry points. Using the <Router basename> prop allows React Router to be easily deployed on only a portion of a larger site by using a portion of the URL pathname (the "basename") to transparently prefix all route paths and link navigations.

    For example, you can deploy one React Router app at the /inbox URL prefix, and another one at the /admin prefix. These base URLs represent two different entry points into your app, each with its own bundles. The rest of your site, including the root / URL could be rendered by something other than React Router, for example by your server framework of choice.

    In the bundle for each entry point, simply initialize React Router with the basename of that entry point.

    <Router basename="/inbox">
      // ...
    </Router>
    

    Then define your routes and link paths without using the /inbox URL prefix in any of them. The entire app will run relative to that prefix.

    Another improvement in this release is the addition of the renderMatches API, which is the complement of matchRoutes. These APIs are both very low-level and should not normally be needed. But they are sometimes nice to use if you are doing your own data loading using the array of matches that you get back from matchRoutes.

    matchRoutes and renderMatches are the equivalent of the react-router-config package we shipped in v4 and v5, just built directly into the router instead of in a separate package.

    πŸ’” Breaking Changes

    • <Routes basename> has moved to <Router basename>. This prop is also available on all router variants (<BrowserRouter>, <HashRouter>, etc.).
    • useLocation().pathname no longer includes the basename, if present.
    • The basename argument was removed from useRoutes. This reverts the signature to useRoutes(routes, location), same as it was previous to beta.4.
    • Descendant <Routes> do not get the params from their parents. This helps a set of <Routes> to be more portable by decoupling it from the params of its parents and makes it easier to know which params will be returned from useParams(). If you were relying on this behavior previously, you'll need to pass along the params manually to the elements rendered by the descendant <Routes>. See this comment for an example of how this is to be done and for a potential workaround if you really need the old behavior.
    • match.pathname in a splat route now includes the portion of the pathname matched by the *. This makes the * param behave much more like other dynamic :id-style params.
    • Resolution of relative <Link>s in splat routes is changed now because the entire pathname that was matched by that route is now different (see previous bullet). Instead of resolving relative to the portion of the pathname before the *, paths resolve relative to the full pathname that was matched by the route.

    πŸ’» Installing

    Development for v6 is chugging along on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    
    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-beta.4(Sep 11, 2021)

    Last week we released a lot of nice little bug features, but we did get a little carried away and let a little bug slip through with relative path resolution. Our bad! That nasty lil' guy is squashed in this week's beta. πŸ›

    And there's more! Let's dive in…

    πŸ› Bugfixes

    • Path resolution for nested relative routes was broken in the last release and should now be fixed. Nested routes construct their pathname based on the location of their parent, not the current location. This is explained in detail under Relative Routes and Links in our advanced guides, and the issue itself in #8004

    ✨ Enhancements

    • We made some enhancements with the Params type which is now generic, so you can add your own types if you know what to expect from functions that return query parameters. (#8019)
    // before
    let { valid, invalid } = useParams(); // No problems here!
    
    let match = useMatch("profile/:userId");
    let userId = match?.params.user; // wrong param, but TS doesn't know that!
    
    // after:
    let { valid, invalid } = useParams<"valid" | "key">(); // Property 'invalid' does not exist on type 'Params<"valid" | "key">'
    
    let match = useMatch<"userId">("profile/:userId");
    let userId = match?.params.user; // Property 'user' does not exist on type 'Params<"userId">'
    
    • Absolute nested path support

    There was quite a bit of discussion in #7335 from people who are using constants to define their route paths. In this style, paths are often written as absolute paths from the root / URL. These constants are then able to be used both in <Route path> definitions as well as <Link to> values. It usually looks something like this:

    const USERS_PATH = "/users";
    const USERS_INDEX_PATH = `${USERS_PATH}/`;
    const USER_PROFILE_PATH = `${USERS_PATH}/:id`;
    
    function UsersRoutes() {
      return (
        <Routes>
          <Route path={USERS_PATH} element={<UsersLayout />}>
            <Route path={USERS_INDEX_PATH} element={<UsersIndex />} />
            <Route path={USER_PROFILE_PATH} element={<UserProfile />} />
          </Route>
        </Routes>
      );
    }
    

    This style of use is now fully supported in v6. This is great for people who write their apps like this, but it technically could cause some breakage if you were using absolute paths (that start with /) in nested routes in previous betas. To fix this, simply remove the / from the beginning of any route paths that are meant to be relative. React Router will throw an error if you are using absolute paths that don't match their parent route paths. Hopefully this should help you find them if you are upgrading.

    If you were using <Route path="/"> to indicate an index route, you can now use the new <Route index> prop to accomplish the same thing. The index prop makes it easy to scan a route config to find the index route. It also provides a guarantee that nobody will ever add children to that route.

    Here's the same route config as the one above, but rewritten with relative paths and the index prop:

    function UsersRoutes() {
      return (
        <Routes>
          <Route path="users" element={<UsersLayout />}>
            <Route index element={<UsersIndex />} />
            <Route path=":id" element={<UserProfile />} />
          </Route>
        </Routes>
      );
    }
    

    A lot of our work on React Router is about doing the least surprising thing for our users. Allowing absolute paths in nested routes gets us a little closer to that goal!

    πŸ’” Breaking Changes

    • Removed the ability for nested route paths to begin with a / and not contain the complete path of their parent routes. This was necessary in order to introduce support for absolute paths in nested routes, described in detail above

    • Removed the createRoutesFromArray utility function. You can now pass your routes directly to useRoutes or matchRoutes without passing it through createRoutesFromArray first

    • Removed the PartialRouteObject type. If you were importing and using this type before, use RouteObject instead, which has been updated to make all properties optional

    • The useRoutes API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object:

    // Before
    useRoutes([...routes], basename);
    
    // After
    useRoutes([...routes], { basename });
    
    • The matchPath function now returns match.pattern instead of match.path, which is a little more descriptive about what it actually is

    πŸ’» Installing

    Development for v6 is chugging along on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    
    Source code(tar.gz)
    Source code(zip)
  • v5.3.0(Sep 3, 2021)

    This release of react-router-dom adds support for passing a function to either the className or style props to conditionally apply values based on the link's active state.

    This provides similar functionality as the existing activeClassName and activeStyle props, but is a bit more powerful. For example, you can now easily apply styles exclusively to an inactive NavLink as well. This offers a nicer experience for folks who use utility class-based CSS tools such as Tailwind.

    function Comp() {
      return (
        <NavLink
          to="/"
          className={isActive =>
            `px-3 py-2 ${isActive ? 'text-gray-200' : 'text-gray-800'}`
          }
        >
          Home
        </NavLink>
      );
    }
    

    Note that as of v6.0.0-beta.3, the activeClassName and activeStyle props are removed completely. Adding support for functional className and style props to both v5 and v6 will give v5 users an easier upgrade path.

    Thanks to @tim-phillips for raising the issue that inspired the change! πŸ₯³

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-beta.3(Sep 3, 2021)

    Loads of goodies for you this week, as well as a few breaking changes for all of you eager beavers who are brave enough to use beta software in production! 🦫

    (seriously, thank you all for helping us tighten up our APIs and fix nasty bugs)

    πŸ’” Breaking Changes!

    • NavLink no longer supports the activeClassName or activeStyle props. Instead, we provide a more powerful API that allows you to pass functions to either the className or style props to conditionally apply values based on the link's active state. While a bit more verbose in some cases, this offers a nicer experience for folks who use utility class-based CSS. (#7194)
    // Before
    <NavLink className="link" activeClassName="active-link" />
    <NavLink style={{ color: "blue" }} activeStyle={{ color: "green" }} />
    
    // After
    <NavLink
      className={({ isActive }) =>
        `link ${
          isActive
            ? "active-link"
            : // Couldn't do this before!
              "inactive-link"
        }`
      }
    />
    <NavLink style={({ isActive }) => ({ color: isActive ? "green" : "blue" })} />
    

    Note: You can always abstract over this feature in a custom NavLink if you prefer the old v5 API.

    • The useRoutes API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object:
    // Before
    useRoutes([...routes], basename);
    
    // After
    useRoutes([...routes], { basename });
    

    πŸ› Bugfixes

    • The basename prop on Routes is treated as case-insensitive (#7997)
    • useNavigate previously used the incorrect pathname when called from parent routes when the URL matches one of its children. This fix also applies to useSearchParams (#7880)

    ✨ Enhancements

    • Routes and useRoutes now allow you to override the location, which may be useful when building some modal interfaces and route transition animations. We are working hard to update our docs to include examples for advanced patterns where this might be useful, but in the mean time this also brings Routes closer to feature parity with v5's Switch via the location prop. (#7117)
    • Provided new hooks useClickHandler and usePressHandler to make customizing Links a bit easier. (#7998)
      • Please note: with great power comes great responsibility. If you create a custom Link, be sure to render an actual HTML anchor element, otherwise your app will likely be inaccessible without a significant amount of additional work which, I assure you, you don't want to do!

    πŸ’» Installing

    Development for v6 is chugging along on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    

    πŸ™ Credits

    Thanks to @andrelandgraf, @dhulme, @fgatti675, @hugmanrique, @MeiKatz, @chaance and @mjackson for your contributions!

    Source code(tar.gz)
    Source code(zip)
  • v5.2.1(Aug 27, 2021)

    This release fixes a bug with <Link> so that, when the to location is the same as the current, the history state entry is replaced instead of pushed to the stack. See https://github.com/remix-run/react-router/issues/5362 for details. πŸ₯³

    Thanks to @guidobouman for the PR and for everyone else who weighed in for the fix!

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-beta.2(Aug 20, 2021)

    πŸ› Bugfixes

    ✨ Enhancements

    πŸ’» Installing

    Development for v6 is chugging along on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    

    πŸ™ Credits

    Thanks to @liho98, @wojtekmaj, @cravend, @chaance and @mjackson for your contributions!

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-beta.1(Aug 13, 2021)

    We're on the road to a stable v6 release!

    There are no new features in this release since beta.0, but a handful of squashed bugs, perf enhancements, and DX improvements for TypeScript users.

    πŸ› Bugfixes

    ✨ Enhancements

    • Internally we are separating navigator into a separate context object, meaning your components that call useNavigate will probably render a little less often. Wowza, much perf!
    • react-router-dom and react-router-native now re-exports all types exported from react-router

    πŸ’» Installing

    Development for v6 is chugging along on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    

    πŸ™ Credits

    Thanks to @brookslybrand, @bogdansoare, @chaance and @mjackson for your contributions!

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v0.0.0-experimental-ffd8c7d0(Jun 19, 2020)

    This release is based on v6.0.0-beta.0 and adds a few features that are targeted at supporting React suspense for data loading. These features are:

    • A timeoutMs prop that may be passed to a <BrowserRouter>, <HashRouter>, <MemoryRouter>, or <NativeRouter>. This timeout dictates how long these routers will wait before transitioning to a new page after the URL has changed. The default timeoutMs is 5000 (5 seconds).
    • useLocationPending hook that returns true if a transition to a new location is pending
    • <Route preload> function that is called whenever a route matches and is about to render. This function is typically used for pre-seeing client-side data caches for data retrieval later during rendering, which may trigger suspense.

    Development on v6's experimental channel is happening on the dev-experimental branch, which tracks all changes that occur on the dev branch.

    What does "experimental" mean?

    React Router v6's experimental release channel follows the same semantics as React's own experimental channel, which means that it is used for features that are not yet ready for a stable release. Use the experimental releases to try out new features before they are released.

    Installing

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    

    Or, if you're on React Native:

    $ yarn add history [email protected]
    

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide. There is also a comprehensive API Reference.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-beta.0(Jun 19, 2020)

    Today we are very happy to release the first beta of React Router version 6!

    Major Features

    No new features in this release since alpha.5, besides the fact that we are now using history v5 stable in various places behind the scenes.

    Major Changes

    There are a few breaking changes from alpha.5:

    • Moved <Route preload> into the experimental release channel
    • Moved useLocationPending into the experimental release channel
    • Made react-router a regular dependency of react-router-dom and react-router-native
    • Made history a peer dependency
    • Renamed useResolvedLocation to useResolvedPath to be more inline with the naming in the history API
    • Renamed resolveLocation to resolvePath to be more inline with the naming in the history API

    Bugfixes

    • We now re-use the sourcemap output from tsc as input into the Rollup toolchain, so sourcemaps go all the way back to the original source instead of stopping at the tsc-generated files

    Docs

    Installing

    Development for v6 is happening on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install history [email protected]
    

    Or, if you're on React Native:

    $ yarn add history [email protected]
    

    Roadmap

    Now that we are in beta, you can expect fewer breaking changes (if any) between releases in the next channel. We are actively developing features targeted at supporting suspense for data loading in the experimental channel. The main thing left to do is documentation and guides (and fix bugs, ofc). If you can spare some time, we'd love to have some help :)

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide. There is also a comprehensive API Reference.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v0.0.0-experimental-b1ff171f(May 27, 2020)

    This release adds support for data fetching with suspense using React's unstable_useTransition API. It is based on v6.0.0-alpha.5.

    Support for suspense is added via a timeoutMs prop that may be passed to a <BrowserRouter>, <HashRouter>, <MemoryRouter>, or <NativeRouter>. Each of these use the prop internally to determine how long to wait to show the new page whenever the URL changes. The default timeoutMs is 5000 (5 seconds).

    What does "experimental" mean?

    React Router v6's experimental release channel follows the same semantics as React's own experimental channel, which means that it is used for features that are not yet ready for a stable release. Use the experimental releases to try out new features before they are released.

    Installing

    Development on v6's experimental channel is happening on the dev-experimental branch.

    If you'd like to test it out, install from npm:

    $ npm install [email protected] [email protected]
    

    Or, if you're on React Native:

    $ yarn add [email protected] [email protected]
    

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-alpha.5(May 15, 2020)

    Major Features

    • Added <Route preload> and route.preload (JSX and useRoutes) APIs. The preload function will be called when the route has matched and is about to render.
    • Added <NavLink end> and <NavLink caseSensitive> to better control matching behavior of <NavLink>s

    Major Changes

    Warning: This release breaks compatibility with 6.0.0-alpha.4

    • Removed the <Router history> prop and moved responsibility for setting up/tearing down the listener (history.listen) into the wrapper components (<BrowserRouter>, <HashRouter>, etc.). <Router> is now a controlled component that just sets up context for the rest of the app.
    • Changed generatePath so it never returns placeholders. Instead, it will throw if a needed placeholder is missing.
    • Removed usage of React's experimental useTransition hook. We will publish our own "experimental" channel very soon with this hook added back in, but it won't be added back to the "next" channel (or stable) until it goes stable in React core.

    Bugfixes

    • Fixed and improved several TypeScript interfaces

    Docs

    • Added some docs for using the basename functionality to the migration guide

    Installing

    Development for v6 is happening on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install [email protected] [email protected]
    

    Or, if you're on React Native:

    $ yarn add [email protected] [email protected]
    

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v5.2.0(May 11, 2020)

    This release includes a notable performance boost by separating the "Router" context from the "History" context internally. We also allow every element type for Link's component prop and support a sensitive prop on NavLink for control over case sensitive matching.

    Enjoy!

    Changes

    • Add sensitive prop on NavLink (#7251 by @caseywebdev)
    • Fix Link component prop type check (#7276 by @ypyakymiv)
    • Update mini-create-react-context (#7288 by @patricksmms)
    • Separate history to its own context (#7103 by @illuminist)
    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-alpha.4(May 5, 2020)

    Lots of great stuff in this release, especially if you like Intellisense :)

    Major Features

    • Migrated the core codebase to TypeScript and added TypeScript declarations
    • Added a migration guide for folks coming from reach/router
    • Added useInRouterContext hook for determining if you're in the context of a router or not
    • Added useLocationPending hook (experimental)
    • Added matchPath function for manually matching paths to URL pathnames

    Note: experimental features rely on an experimental release of React and will probably be moved into a separate "experimental" release channel in the near future.

    Major Changes

    Warning: This release breaks compatibility with 6.0.0-alpha.3

    • useSearchParams now returns [searchParams, setSearchParams] (similar to useState). setSearchParams is a wrapper for navigate that updates the query string on the current URL. See the updated guide on working with the query string.
    • Removed the <StaticRouter context> API. We don't support navigation on the initial render in v6, so this API is unnecessary.
    • useMatch takes a route path (instead of a link to value as it did previously). It should have always taken a route path; this was just a simple oversight.

    Bugfixes

    • Fixed a bug with multiple nested * routes
    • Force stable sort in browsers that don't have it so routes that otherwise rank equally maintain the order in which they were originally defined

    Installing

    Development for v6 is happening on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install [email protected] [email protected]
    

    Or, if you're on React Native:

    $ yarn add [email protected] [email protected]
    

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-alpha.3(Apr 4, 2020)

    Major Features

    • Added a new useSearchParams hook (see f59ee5488bc343cf3c957b7e0cc395ef5eb572d2)

    The useSearchParams hook returns a URLSearchParams object created from the current location.search string. This is a feature that people have wanted for a while, but we were always hesitant to ship a full-blown query parser with the router. Well, now that we have URLSearchParams widely available, we don't have to. I wrote up a small guide about how to use useSearchParams if you'd like to read more.

    Major Changes

    Warning: This release breaks compatibility with 6.0.0-alpha.2

    • Redirect (and redirectTo in useRoutes) was removed (see cbcd398276efaad31e5e994fdb2f80ca454eb859)
    • We no longer support redirecting on the initial render, due to compatibility issues with future versions of React

    React won't let us change the state in an ancestor component on the initial render w/out warning, so we had to remove the <Redirect> component, as well as the ability to do a navigate() on the initial render. You can still render a <Navigate>, but it won't actually update the page until the next render.

    If you really need to redirect on the initial render, you can either a) do it on your server (probably best, so it can be cached at the HTTP level instead of doing it in every user's browser) or b) do it outside of React Router (e.g. using the history API directly).

    Installing

    Development for v6 is happening on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install [email protected] react[email protected]
    

    Or, if you're on React Native:

    $ yarn add [email protected] [email protected]
    

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v3.2.6(Mar 4, 2020)

  • v6.0.0-alpha.2(Feb 22, 2020)

    This release fixes a few bugs with the previous alpha, namely:

    • Fix a few path matching corner cases
    • Fix rendering <Link>s on the server (see https://github.com/ReactTraining/react-router/pull/7126, thanks @danpantry)

    Also, we added a new doc about adding React Router to your web project whether you're using create-react-app, Webpack, Parcel, or just plain 'ol <script> tags. Thanks @chancestrickland!

    Development for v6 is happening on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install [email protected] [email protected]
    

    Or, if you're on React Native:

    $ yarn add [email protected] [email protected]
    

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-alpha.1(Feb 1, 2020)

  • v6.0.0-alpha.0(Jan 31, 2020)

    First alpha release of the next major version of React Router, version 6. A few of the highlights are:

    • Relative routes and links
    • Nested <Route>s
    • Automatic<Route> ranking with a new <Routes> API
    • New suspense-ready navigate API
    • useRoutes + matchRoutes for using object-based routing API

    Development for v6 is happening on the dev branch.

    If you'd like to test it out, install from npm:

    $ npm install [email protected] [email protected] [email protected]
    

    Or, if you're on React Native:

    $ yarn add [email protected] [email protected] [email protected]
    

    We are actively working on documentation. For now, if you're just interested in testing things out you may be interested in the getting started guide. If you're interested in upgrading an existing app, please check out the v5 to v6 migration guide.

    Please note that although there are several breaking changes we are still working on the migration path and will continue to publish improvements and helpers in v5 that should help you upgrade as smoothly as possible. We are not done with v5. Heck, we're still cutting releases of v3.

    This release addresses several long-standing issues and pitfalls with previous releases. We are focused on providing a smooth upgrade path for both v4/5 users and v3 users who would like to make the jump to v6. We will be publishing more very soon.

    Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v3.2.5(Oct 25, 2019)

    Changes

    • Fix React version detection for UNSAFE_ lifecycles (fixes issues with React 16.10) (#6961 by @henryqdineen)
    • Add element shape for Link's innerRef prop (#6886 by @nescalante)
    Source code(tar.gz)
    Source code(zip)
  • v5.1.2(Sep 30, 2019)

  • v5.1.1(Sep 27, 2019)

    List of commits

    Bugfixes

    • Fix issue with useParams reading from null object (#6940)
    • Fix regression passing ref to functional components in React <= 16.2 (#6934)
    • Fix regression passing empty string to matchPath (#6941)
    Source code(tar.gz)
    Source code(zip)
  • v5.1.0(Sep 24, 2019)

    Read the blog post

    List of commits

    Features

    • Add useParams, useLocation, useHistory, and useRouteMatch hooks (d6224d6a)
    • Add support for forwardRef in <Link> (b5528ed6)
    • Add support for functions in <Link to> and <NavLink to> (#5331, #5368)
    • Add <Link component> API (#5437)

    Bugfixes

    • Don't render <Route children> elements when the <Route> does not match (96656595)
    Source code(tar.gz)
    Source code(zip)
  • v3.2.4(Aug 23, 2019)

  • v3.2.3(Jun 26, 2019)

  • v3.2.2(Jun 25, 2019)

  • v5.0.1(Jun 4, 2019)

    Changes

    Updates

    • Reduced component depth in withRouter() HOC. (10d78bb)
    • Changed misleading warning when withRouter is used outside a Router (10d78bb)
    • Reduced install size and bundle size by switching to mini-create-react-context (992af48)

    Bugfixes

    • Fixed display name for router context consumer and provider (6a99c93)
    • Fixed infinite loop caused by Redirect in some scenarios (017f692 and 2ce1d32)
    • Fixed license issue for react context polyfill (f9849c8, then 992af48)
    • Fixed Redirect throwing an exception in StaticRouter without context (3ccbd19)
    • Fixed regression in matchPath that caused an exception for empty paths (7bd1407)
    • Fixed page reload when an exception was thrown in Link onClick (82ce94c)
    • Fixed warning about createRef or useRef values in wrappedComponentRef when using withRouter() (56c829b)
    • Fixed withRouter() wrapped component inside NavLink not working properly (a38ef04)
    • Fixed CJS build - previously, incorrect exports were emitted (caa9950)

    Thanks to @StringEpsilon for putting this list together. Enjoy!

    Source code(tar.gz)
    Source code(zip)
  • v5.0.0(Mar 18, 2019)

    Note: While this does have a major version bump, it is actually a minor release. We screwed up some of the dependency version selection in 4.3.1, which necessitated a major bump. See this blog post for details.

    ⚠️ Upgrade Warning ⚠️

    Please ensure you have upgraded both react-router and react-router-dom (react-router-native for RN users) to the exact same version. If different versions of those two packages are in your application, you will get errors when using <Link> and other react-router-dom-specific components. You can ensure you have the correct versions of both packages in your app using npm ls react-router react-router-dom.

    Breaking Changes

    • Since the old context API is no longer used, any access to the old context will fail. Use of the react router context is not supported, please use withRouter() or a <Route/> instead.
    • Due to the new context API, mixing of imports will now result in an exception:
    // Be careful, this won't work anymore!
    import BrowserRouter from 'react-router-dom/BrowserRouter';
    import { Route } from 'react-router-dom';
    
    <BrowserRouter>
      <Route />
    </BrowserRouter>
    

    Refactor as follows:

    // These are both from the same build and use the same context object
    // so there won't be a mismatch :)
    import { BrowserRouter, Route } from 'react-router-dom';
    
    • In development mode, we now throw an error when using 2 different builds (see b2c6fa0), i.E. combining CJS imports with ESM imports.

    New Features

    • <Route /> now supports an array of paths - #5889 (thanks @baronswindle)
    <Route path={["/BigApple", "/NYC", "NewYork"]} component={NewYork} />
    

    Full Changelog

    • <Route /> now supports multiple child nodes when using react >= 16.0.
    • Migrated to new react context API, with a polyfill for react versions < 16.2
    • Removed deprecated lifecycle methods componentWillMount and componentWillReceiveProps
    • Introduced more warnings in development builds
    • Changed build-process to rollup:
      • Smaller build size
      • Package now includes pre-minified files
      • Package now consists of single-file builds that include all modules.
    • Upgraded to history 4.9.0
    • Per file imports are deprecated and will be removed in a future major version. For now, a warning will be logged.
    • Made sure that react router conforms to react <StrictMode/>
    • Fixed <Link /> not working properly with target="_self" - #6138 (thanks @ericyang89)
    • Fixed prop-type warning when using forwardRef - #6417 (thanks @frehner and @eXon)
    • Added support for createRef in - #6567 (thanks @gcangussu)
    • Removed use of eval in development to be compliant with unsafe-eval CSP - #6611
    • Migrated to babel-preset-env
    • Improved testing infrastructure to improve developer workflow
    • Several docs improvements - #6410 (thanks @justsml)
    Source code(tar.gz)
    Source code(zip)
  • v4.4.0-beta.8(Mar 15, 2019)

Owner
React Training
High-quality open source software from React Training
React Training
A simple, declarative, and composable way to fetch data for React components

React Refetch A simple, declarative, and composable way to fetch data for React components. Installation Requires React 0.14 or later. npm install --s

Heroku 3.4k Oct 16, 2021
Declarative routing for React

React Router Declarative routing for React Docs View the docs here Migrating from 2.x/3.x? 3.x docs 2.x docs Packages This repository is a monorepo th

React Training 44.2k Oct 11, 2021
A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform

React Redux Universal Hot Example About This is a starter boilerplate app I've put together using the following technologies: Isomorphic Universal ren

Erik Rasmussen 12.1k Oct 9, 2021
:fire: A highly scalable, offline-first foundation with the best developer experience and a focus on performance and best practices.

Start your next react project in seconds A highly scalable, offline-first foundation with the best DX and a focus on performance and best practices Cr

react-boilerplate 27.9k Oct 11, 2021
Relay is a JavaScript framework for building data-driven React applications.

Relay Β· Relay is a JavaScript framework for building data-driven React applications. Declarative: Never again communicate with your data store using a

Facebook 16k Oct 21, 2021
A Foundation for Scalable Cross-Platform Apps

Electron React Boilerplate uses Electron, React, React Router, Webpack and React Fast Refresh. Install If you have installation or compilation issues

Electron React Boilerplate 18.4k Oct 18, 2021
React bindings for MobX

mobx-react ?? ?? ?? This repo has been moved to mobx Package with React component wrapper for combining React with MobX. Exports the observer decorato

MobX 4.8k Oct 14, 2021
Seamless mapping of class names to CSS modules inside of React components.

React CSS Modules React CSS Modules implement automatic mapping of CSS modules. Every CSS class is assigned a local-scoped identifier with a global un

Gajus Kuizinas 5.2k Oct 9, 2021
Set up a modern web app by running one command.

Create React App Create React apps with no build configuration. Creating an App – How to create a new app. User Guide – How to develop apps bootstrapp

Facebook 90.9k Oct 14, 2021
πŸ“‹ React Hooks for forms validation (Web + React Native)

Version 7 | Version 6 Features Built with performance and DX in mind Embraces native form validation Out of the box integration with UI libraries Smal

React Hook Form 23.6k Oct 13, 2021
:rocket: Blazing fast page load and seamless navigation.

React Server is now defunct Consider Next.js instead. React Server React framework with server render for blazing fast page load and seamless transiti

Redfin 3.9k Oct 4, 2021
Official React bindings for Redux

React Redux Official React bindings for Redux. Performant and flexible. Installation Using Create React App The recommended way to start new apps with

Redux 21.5k Oct 18, 2021
A toolkit for React, Preact, Inferno & vanilla JS apps, React libraries and other npm modules for the web, with no configuration (until you need it)

nwb nwb is a toolkit for: Quick Development with React, Inferno, Preact or vanilla JavaScript Developing: React Apps Preact Apps Inferno Apps Vanilla

Jonny Buchanan 5.4k Oct 18, 2021
Yeoman generator for ReactJS and Webpack

generator-react-webpack Yeoman generator for ReactJS - lets you quickly set up a project including karma test runner and Webpack module system. About

null 2.9k Oct 15, 2021
🏁 High performance subscription-based form state management for React

You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of React Final Form.

Final Form 6.7k Oct 15, 2021
CSS media queries in react - for responsive design, and more.

react-responsive Information Package react-responsive Description Media queries in react for responsive design Browser Version >= IE6* Demo The best s

contra 5.8k Oct 13, 2021
:recycle: React integration for Apollo Client

React Apollo ⚠️ THIS PROJECT HAS BEEN DEPRECATED ⚠️ Please note that 4.0.0 is the final version of all React Apollo packages. React Apollo functionali

Apollo GraphQL 6.9k Oct 15, 2021
Isomorphic flux implementation

alt Check out the API Reference for full in-depth docs. For a high-level walk-through on flux, take a look at the Getting Started guide. What follows

Josh Perez 3.5k Oct 15, 2021
A React component for building Web forms from JSON Schema.

react-jsonschema-form A simple React component capable of using JSON Schema to declaratively build and customize web forms. Explore the docs Β» View Pl

null 10.7k Oct 13, 2021