Declarative routing for React

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!

Comments
  • 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
  • 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
  • this.context.router is undefined

    this.context.router is undefined

    I just upgraded to react-router (and react) 0.13, and got rid of all the deprecated State mixins. Using this.context.router doesn't seem to work. I just see this everywhere:

    Uncaught TypeError: Cannot read property 'getParams' of undefined
    

    Is there anything additional I need to do?


    Edit by Ryan Florence to get people to the answer right here at the top of the issue :dancer:

    Check out the upgrade guide: https://github.com/rackt/react-router/blob/master/UPGRADE_GUIDE.md#012x---013x

    Sorry it wasn't done w/ the release, it's been an abnormally busy month for us since we quit our jobs and started a new business :P

    opened by tjwebb 94
  • ActiveState changes don't propagate if any single parent in hierarchy declares shouldComponentUpdate

    ActiveState changes don't propagate if any single parent in hierarchy declares shouldComponentUpdate

    If I have a component using ActiveState mixin and some of its parents declare shouldComponentUpdate, the child won't update when active state changes.

    This is not normal because usually parent's shouldComponentUpdate doesn't magically cut the child off updates. If child listens to some store and calls setState, it will be updated. But this is not the case with context.

    Even if parent's shouldComponentUpdate implementation takes nextContext into account, it won't even get nextContext if it doesn't declare contextTypes itself. So basically, for ActiveState to work in a project that heavily uses shallow-comparing shouldComponentUpdate or something similar, all ancestors of ActiveState-using component need to also have ActiveState.

    See this React issue and this fiddle.

    Obviously it's a React's problem per se but since router relies on context so much, it's worth documenting.

    bug 
    opened by gaearon 87
  • test(useNavigate): navigate with an defined and empty query string

    test(useNavigate): navigate with an defined and empty query string

    I was tracking down a bug and to make sure it wasn't a bug in react-router I looked for tests of useNavigate. I saw there is no test of useNavigate that expects navigate to clear the query string.

    That's it. This PR just add a single test.

    CLA Signed 
    opened by JesusTheHun 3
  • [Feature]: Document Path pattern syntax

    [Feature]: Document Path pattern syntax

    What is the new or updated feature that you are suggesting?

    There's been a lot of new syntax added to paths which isn't documented all in one place. There should be a single source in the public doc site that contains every symbol that can be used, what it is used for, and examples for each.

    It seems like here is where this is already started, but not complete. It references the use of - which seems to indicate optional segments. And doesn't document the new ? for optional segments. I'm not sure what other secret features might be available or what advanced ways they might be used since I cannot find information about them aside from release notes.

    Why should this feature be included?

    Visibility into the core feature of React Router. The path strings include a lot of special syntax which is unique but poorly documented which leads to word-of-mouth features and a lot of confusion.

    feature 
    opened by CreativeTechGuy 0
  • [Bug]: Navigate(-1) not working in safari 16.*

    [Bug]: Navigate(-1) not working in safari 16.*

    What version of React Router are you using?

    6.6.1

    Steps to Reproduce

    1. Use BrowserRouter as your router.
    2. Create a button and set its onClick to () => navigate(-1).
    3. Build the project in production mode.
    4. Open app with the Safari iOS 16.
    5. Click on button

    Expected Behavior

    URL should change and the page's content should change.

    Actual Behavior

    URL will change but the content will not update, and by a reload the state will fix.

    The source of the bug is that safari 16 will not support the popstate event properly, it only triggers on page load when we are using react (SPA), so it's useless.
    This problem will cause handlePop not to trigger and the state of BrowserRouter will not update.

    bug 
    opened by mseyfayi 1
  • [Bug]: createMemoryRouter is dependant on Web APIs

    [Bug]: createMemoryRouter is dependant on Web APIs

    What version of React Router are you using?

    6.6.0

    Steps to Reproduce

    Create data router using createMemoryRouter(...) and <RouterProvider ...>, use redirect() or navigate() in environment that it neither test env nor a browser.

    Expected Behavior

    Internal current route should change to the one provided in redirect() or navigate() (as it currently does when using <MemoryRouter>).

    Actual Behavior

    An error is being thrown:

    ReferenceError: window is not defined
        at createClientSideURL (/home/yiin/projects/wicked/node_modules/@remix-run/router/history.ts:570:9)
        at createClientSideRequest (/home/yiin/projects/wicked/node_modules/@remix-run/router/router.ts:2900:13)
        at startNavigation (/home/yiin/projects/wicked/node_modules/@remix-run/router/router.ts:959:19)
        at Object.navigate (/home/yiin/projects/wicked/node_modules/@remix-run/router/router.ts:859:18)
    
    bug 
    opened by Yiin 2
  • [Feature]: Add optional path segment support to useMatch/matchPath

    [Feature]: Add optional path segment support to useMatch/matchPath

    What is the new or updated feature that you are suggesting?

    Optional path segment handling in matchPath and useMatch.

    Currently it is supported in Route definitions, but not when matching an arbitrary route pattern:

    image

    Why should this feature be included?

    Feature parity between how <Route /> components are defined and how direct usage of matchPath and useMatch works.

    feature 
    opened by rossipedia 0
  • [Feature]: Allow loader functions to be generators

    [Feature]: Allow loader functions to be generators

    What is the new or updated feature that you are suggesting?

    Allow loader functions to be async generators.

    The first time the function yielded a value, React Router would be able to render the element, and the most recently-yielded value would be available through useLoaderData. React Router would then await the next value, and re-render when it yielded. Returning a value from the loader would cause a final render.

    If the user navigated away from the route with the loader, React Router would stop requesting additional values from the generator.

    With SSR, React Router could loop until the generator returned, ignoring the intermediate yielded values and only rendering the final result.

    Why should this feature be included?

    This is a more general, more flexible way of managing the current defer / <Await> pattern for partial data.

    Async generators make the stale-while-revalidate pattern straightforward to implement, as they can yield stale data immediately, then wait for the revalidated data before returning.

    This can also be used for data that is streamed in in chunks, as the loader could yield after each page of data is returned and the component could render what was available each time.

    feature 
    opened by fionawhim 0
  • [email protected](Dec 23, 2022)

  • [email protected](Dec 21, 2022)

    What's Changed

    This minor release is primarily to stabilize our SSR APIs for Data Routers now that we've wired up the new RouterProvider in Remix as part of the React Router-ing Remix work.

    Minor Changes

    • Remove unstable_ prefix from createStaticHandler/createStaticRouter/StaticRouterProvider (#9738)
    • Add useBeforeUnload() hook (#9664)

    Patch Changes

    • Support uppercase <Form method> and useSubmit method values (#9664)
    • Fix <button formmethod> form submission overriddes (#9664)
    • Fix explicit replace on submissions and PUSH on submission to new paths (#9734)
    • Prevent useLoaderData usage in errorElement (#9735)
    • Proper hydration of Error objects from StaticRouterProvider (#9664)
    • Skip initial scroll restoration for SSR apps with hydrationData (#9664)
    • Fix a few bugs where loader/action data wasn't properly cleared on errors (#9735)

    Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.6.0

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Dec 16, 2022)

    What's Changed

    This release introduces support for Optional Route Segments. Now, adding a ? to the end of any path segment will make that entire segment optional. This works for both static segments and dynamic parameters.

    Optional Params Examples

    • <Route path=":lang?/about> will match:
      • /:lang/about
      • /about
    • <Route path="/multistep/:widget1?/widget2?/widget3?"> will match:
      • /multistep
      • /multistep/:widget1
      • /multistep/:widget1/:widget2
      • /multistep/:widget1/:widget2/:widget3

    Optional Static Segment Example

    • <Route path="/home?"> will match:
      • /
      • /home
    • <Route path="/fr?/about"> will match:
      • /about
      • /fr/about

    Minor Changes

    • Allows optional routes and optional static segments (#9650)

    Patch Changes

    • Stop incorrectly matching on partial named parameters, i.e. <Route path="prefix-:param">, to align with how splat parameters work. If you were previously relying on this behavior then it's recommended to extract the static portion of the path at the useParams call site: (#9506)
    // Old behavior at URL /prefix-123
    <Route path="prefix-:id" element={<Comp /> }>
    
    function Comp() {
      let params = useParams(); // { id: '123' }
      let id = params.id; // "123"
      ...
    }
    
    // New behavior at URL /prefix-123
    <Route path=":id" element={<Comp /> }>
    
    function Comp() {
      let params = useParams(); // { id: 'prefix-123' }
      let id = params.id.replace(/^prefix-/, ''); // "123"
      ...
    }
    
    • Persist headers on loader request's after SSR document action request (#9721)
    • Fix requests sent to revalidating loaders so they reflect a GET request (#9660)
    • Fix issue with deeply nested optional segments (#9727)
    • GET forms now expose a submission on the loading navigation (#9695)
    • Fix error boundary tracking for multiple errors bubbling to the same boundary (#9702)

    Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.5.0

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Dec 7, 2022)

    What's Changed

    • Fix requests sent to revalidating loaders so they reflect a GET request (#9680)
    • Remove instanceof Response checks in favor of isResponse (#9690)
    • Fix URL creation in Cloudflare Pages or other non-browser-environments (#9682, #9689)
    • Add requestContext support to static handler query/queryRoute (#9696)
      • Note that the unstable API of queryRoute(path, routeId) has been changed to queryRoute(path, { routeId, requestContext })

    Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.4.5

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Nov 30, 2022)

    What's Changed

    • Throw an error if an action/loader function returns undefined as revalidations need to know whether the loader has previously been executed. undefined also causes issues during SSR stringification for hydration. You should always ensure your loader/action returns a value, and you may return null if you don't wish to return anything. (#9511)
    • Properly handle redirects to external domains (#9590, #9654)
    • Preserve the HTTP method on 307/308 redirects (#9597)
    • Support basename in static data routers (#9591)
    • Enhanced ErrorResponse bodies to contain more descriptive text in internal 403/404/405 scenarios
    • Fix issues with encoded characters in NavLink and descendant <Routes> (#9589, #9647)
    • Properly serialize/deserialize ErrorResponse instances when using built-in hydration (#9593)
    • Support basename in static data routers (#9591)
    • Updated dependencies:

    Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.4.4

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Nov 1, 2022)

    What's Changed

    • Generate correct <a href> values when using createHashRouter (#9409)
    • Better handle encoding/matching with special characters in URLs and route paths (#9477, #9496)
    • Generate correct formAction pathnames when an index route also has a path (#9486)
    • Respect relative=path prop on NavLink (#9453)
    • Fix NavLink behavior for root urls (#9497)
    • useRoutes should be able to return null when passing locationArg (#9485)
    • Fix initialEntries type in createMemoryRouter (#9498)
    • Support basename and relative routing in loader/action redirects (#9447)
    • Ignore pathless layout routes when looking for proper submission action function (#9455)
    • Add UMD build for @remix-run/router (#9446)
    • Fix createURL in local file execution in Firefox (#9464)

    New Contributors

    • @danielberndt made their first contribution in #9485
    • @AchThomas made their first contribution in #9464
    • @manzano78 made their first contribution in #9451

    Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.4.3

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Oct 6, 2022)

    What's Changed

    • Respect basename in useFormAction (#9352)
    • Fix IndexRouteObject and NonIndexRouteObject types to make hasErrorElement optional (#9394)
    • Enhance console error messages for invalid usage of data router hooks (#9311)
    • If an index route has children, it will result in a runtime error. We have strengthened our RouteObject/RouteProps types to surface the error in TypeScript. (#9366)

    Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.4.2

    Source code(tar.gz)
    Source code(zip)
  • v5.3.4(Oct 2, 2022)

    We removed the mini-create-react-context dependency, moving it into an internal module to eliminate peer dependency warnings for users on React 18 (#9382).

    Full Changelog: https://github.com/remix-run/react-router/compare/v5.3.3...v5.3.4

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Sep 22, 2022)

  • [email protected](Sep 13, 2022)

    Whoa this is a big one! 6.4.0 brings all the data loading and mutation APIs over from Remix. Here's a quick high level overview, but it's recommended you go check out the docs, especially the feature overview and the tutorial.

    New APIs

    • Create your router with createMemoryRouter
    • Render your router with <RouterProvider>
    • Load data with a Route loader and mutate with a Route action
    • Handle errors with Route errorElement
    • Defer non-critical data with defer and Await

    react-router-dom APIs

    • Create your router with createBrowserRouter/createHashRouter
    • Submit data with the new <Form> component
    • Perform in-page data loads and mutations with useFetcher()
    • Defer non-critical data with defer and Await
    • Manage scroll position with <ScrollRestoration>
    • Perform path-relative navigations with <Link relative="path"> (#9160)

    Bug Fixes

    • Path resolution is now trailing slash agnostic (#8861)
    • useLocation returns the scoped location inside a <Routes location> component (#9094)
    • Respect the <Link replace> prop if it is defined (#8779)
    Source code(tar.gz)
    Source code(zip)
  • @remix-run/[email protected](Sep 13, 2022)

    This is the first stable release of @remix-run/router, which provides all the underlying routing and data loading/mutation logic for react-router. You should not be using this package directly unless you are authoring a routing library similar to react-router.

    For an overview of the features provided by react-router, we recommend you go check out the docs, especially the feature overview and the tutorial.

    For an overview of the features provided by @remix-run/router, please check out the README.

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Sep 8, 2022)

    Patch Changes

    • fix: remove internal router singleton (#9227)

      This change removes the internal module-level routerSingleton we create and maintain inside our data routers since it was causing a number of headaches for non-simple use cases:

      • Unit tests are a pain because you need to find a way to reset the singleton in-between tests
        • Use use a _resetModuleScope singleton for our tests
        • ...but this isn't exposed to users who may want to do their own tests around our router
      • The JSX children <Route> objects cause non-intuitive behavior based on idiomatic react expectations
        • Conditional runtime <Route>'s won't get picked up
        • Adding new <Route>'s during local dev won't get picked up during HMR
        • Using external state in your elements doesn't work as one might expect (see #9225)

      Instead, we are going to lift the singleton out into user-land, so that they create the router singleton and manage it outside the react tree - which is what react 18 is encouraging with useSyncExternalStore anyways! This also means that since users create the router - there's no longer any difference in the rendering aspect for memory/browser/hash routers (which only impacts router/history creation) - so we can get rid of those and trim to a simple RouterProvider

      // Before
      function App() {
        <DataBrowserRouter>
          <Route path="/" element={<Layout />}>
            <Route index element={<Home />}>
          </Route>
        <DataBrowserRouter>
      }
      
      // After
      let router = createBrowserRouter([{
        path: "/",
        element: <Layout />,
        children: [{
          index: true,
          element: <Home />,
        }]
      }]);
      
      function App() {
        return <RouterProvider router={router} />
      }
      

      If folks still prefer the JSX notation, they can leverage createRoutesFromElements (aliased from createRoutesFromChildren since they are not "children" in this usage):

      let routes = createRoutesFromElements(
        <Route path="/" element={<Layout />}>
          <Route index element={<Home />}>
        </Route>
      );
      let router = createBrowserRouter(routes);
      
      function App() {
        return <RouterProvider router={router} />
      }
      

      And now they can also hook into HMR correctly for router disposal:

      if (import.meta.hot) {
        import.meta.hot.dispose(() => router.dispose());
      }
      

      And finally since <RouterProvider> accepts a router, it makes unit testing easer since you can create a fresh router with each test.

      Removed APIs

      • <DataMemoryRouter>
      • <DataBrowserRouter>
      • <DataHashRouter>
      • <DataRouterProvider>
      • <DataRouter>

      Modified APIs

      • createMemoryRouter/createBrowserRouter/createHashRouter used to live in @remix-run/router to prevent devs from needing to create their own history. These are now moved to react-router/react-router-dom and handle the RouteObject -> AgnosticRouteObject conversion.

      Added APIs

      • <RouterProvider>
      • createRoutesFromElements (alias of createRoutesFromChildren)
    • Updated dependencies

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Aug 31, 2022)

  • [email protected](Aug 2, 2022)

    Patch Changes

    • c3406eb9: fix: Rename <Deferred> to <Await> (#9095)

      • We are no longer replacing the Promise on loaderData with the value/error when it settles so it's now always a Promise.
      • To that end, we changed from <Deferred value={promise}> to <Await resolve={promise}> for clarity, and it also now supports using <Await> with raw promises from anywhere, not only those on loaderData from a defer() call.
        • Note that raw promises will not be automatically cancelled on interruptions so they are not recommended
      • The hooks are now useAsyncValue/useAsyncError
    • Updated dependencies

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Aug 2, 2022)

  • [email protected](Aug 2, 2022)

  • @remix-run/[email protected](Aug 2, 2022)

    Patch Changes

    • c3406eb9: fix: Rename <Deferred> to <Await> (#9095)

      • We are no longer replacing the Promise on loaderData with the value/error when it settles so it's now always a Promise.
      • To that end, we changed from <Deferred value={promise}> to <Await resolve={promise}> for clarity, and it also now supports using <Await> with raw promises from anywhere, not only those on loaderData from a defer() call.
        • Note that raw promises will not be automatically cancelled on interruptions so they are not recommended
      • The hooks are now useAsyncValue/useAsyncError
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Jul 22, 2022)

    Patch Changes

    • feat: Deferred API Updates (#9070)

      • Removes <Suspense> from inside <Deferred>, requires users to render their own suspense boundaries
      • Updates Deferred to use a true error boundary to catch render errors as well as data errors
      • Support array and single promise usages
        • return deferred([ await critical(), lazy() ])
        • return deferred(lazy())
      • Remove Deferrable/ResolvedDeferrable in favor of raw Promise's and Awaited
      • Remove generics from useDeferredData until useLoaderData generic is decided in 6.5
    • Updated dependencies

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Jul 22, 2022)

  • [email protected](Jul 22, 2022)

    Patch Changes

    • SSR Updates for React Router (#9058)

      Note: The Data-Router SSR aspects of @remix-run/router and react-router-dom are being released as unstable in this release (unstable_createStaticHandler and unstable_DataStaticRouter), and we plan to finalize them in a subsequent minor release once the kinks can be worked out with the Remix integration. To that end, they are available for use, but are subject to breaking changes in the next minor release.

      • Remove useRenderDataRouter() in favor of <DataRouterProvider>/<DataRouter>
      • Support automatic hydration in <DataStaticRouter>/<DataBrowserRouter>/<DataHashRouter>
        • Uses window.__staticRouterHydrationData
        • Can be disabled on the server via <DataStaticRouter hydrate={false}>
        • Can be disabled (or overridden) in the browser by passing hydrationData to <DataBrowserRouter>/<DataHashRouter>
      • <DataStaticRouter> now tracks it's own SSR error boundaries on StaticHandlerContext
      • StaticHandlerContext now exposes statusCode/loaderHeaders/actionHeaders
      • foundMissingHydrationData check removed since Remix routes may have loaders (for modules) that don't return data for loaderData
    • Updated dependencies

    Source code(tar.gz)
    Source code(zip)
  • @remix-run/[email protected](Jul 22, 2022)

    Patch Changes

    • feat: Deferred API Updates (#9070)

      • Support array and single promise usages
        • return deferred([ await critical(), lazy() ])
        • return deferred(lazy())
      • Remove Deferrable/ResolvedDeferrable in favor of raw Promise's and Awaited
      • Remove generics from useDeferredData until useLoaderData generic is decided in 6.5
    • feat: Add createStaticRouter for @remix-run/router SSR usage (#9013)

      Notable changes:

      • request is now the driving force inside the router utils, so that we can better handle Request instances coming form the server (as opposed to string and Path instances coming from the client)
      • Removed the signal param from loader and action functions in favor of request.signal

      Example usage (Document Requests):

      // Create a static handler
      let { query } = unstable_createStaticHandler(routes);
      
      // Perform a full-document query for the incoming Fetch Request.  This will
      // execute the appropriate action/loaders and return either the state or a
      // Fetch Response in the case of redirects.
      let state = await query(fetchRequest);
      
      // If we received a Fetch Response back, let our server runtime handle directly
      if (state instanceof Response) {
        throw state;
      }
      
      // Otherwise, render our application providing the data routes and state
      let html = ReactDOMServer.renderToString(
        <React.StrictMode>
          <DataStaticRouter routes={routes} state={state} />
        </React.StrictMode>
      );
      

      Example usage (Data Requests):

      // Create a static route handler
      let { queryRoute } = unstable_createStaticHandler(routes);
      
      // Perform a single-route query for the incoming Fetch Request.  This will
      // execute the appropriate singular action/loader and return either the raw
      // data or a Fetch Response
      let data = await queryRoute(fetchRequest);
      
      // If we received a Fetch Response back, return it directly
      if (data instanceof Response) {
        return data;
      }
      
      // Otherwise, construct a Response from the raw data (assuming json here)
      return new Response(JSON.stringify(data), {
        headers: {
          "Content-Type": "application/json; charset=utf-8",
        },
      });
      
    • feat: SSR Updates for React Router (#9058)

      Note: The Data-Router SSR aspects of @remix-run/router and react-router-dom are being released as unstable in this release (unstable_createStaticHandler and unstable_DataStaticRouter), and we plan to finalize them in a subsequent minor release once the kinks can be worked out with the Remix integration. To that end, they are available for use, but are subject to breaking changes in the next minor release.

      • Remove useRenderDataRouter() in favor of <DataRouterProvider>/<DataRouter>
      • Support automatic hydration in <DataStaticRouter>/<DataBrowserRouter>/<DataHashRouter>
        • Uses window.__staticRouterHydrationData
        • Can be disabled on the server via <DataStaticRouter hydrate={false}>
        • Can be disabled (or overridden) in the browser by passing hydrationData to <DataBrowserRouter>/<DataHashRouter>
      • <DataStaticRouter> now tracks it's own SSR error boundaries on StaticHandlerContext
      • StaticHandlerContext now exposes statusCode/loaderHeaders/actionHeaders
      • foundMissingHydrationData check removed since Remix routes may have loaders (for modules) that don't return data for loaderData
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Jul 14, 2022)

    Patch Changes

    • Feat: adds deferred support to data routers (#9002)

      Returning a deferred from a loader allows you to separate critical loader data that you want to wait for prior to rendering the destination page from non-critical data that you are OK to show a spinner for until it loads.

      // In your route loader, return a deferred() and choose per-key whether to
      // await the promise or not.  As soon as the awaited promises resolve, the
      // page will be rendered.
      function loader() {
        return deferred({
          critical: await getCriticalData(),
          lazy: getLazyData(),
        });
      };
      
      // In your route element, grab the values from useLoaderData and render them
      // with <Deferred>
      function DeferredPage() {
        let data = useLoaderData();
        return (
          <>
            <p>Critical Data: {data.critical}</p>
            <Deferred
              value={data.lazy}
              fallback={<p>Loading...</p>}
              errorElement={<RenderDeferredError />}>
              <RenderDeferredData />
            </Deferred>
          </>
        );
      }
      
      // Use separate components to render the data once it resolves, and access it
      // via the useDeferredData hook
      function RenderDeferredData() {
        let data = useDeferredData();
        return <p>Lazy: {data}</p>;
      }
      
      function RenderDeferredError() {
        let data = useRouteError();
        return <p>Error! {data.message} {data.stack}</p>;
      }
      

      If you want to skip the separate components, you can use the Render Props pattern and handle the rendering of the deferred data inline:

      function DeferredPage() {
        let data = useLoaderData();
        return (
          <>
            <p>Critical Data: {data.critical}</p>
            <Deferred value={data.lazy} fallback={<p>Loading...</p>}>
              {(data) => <p>{data}</p>}
            </Deferred>
          </>
        );
      }
      
    • feat: add basename support for data routers (#9026)

    • fix: Fix trailing slash behavior on pathless routing when using a basename (#9045)

    • Updated dependencies

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Jul 14, 2022)

  • [email protected](Jul 14, 2022)

  • @remix-run/[email protected](Jul 14, 2022)

    Patch Changes

    • fix: Handle fetcher 404s as normal boundary errors (#9015)
    • feat: adds deferred support to data routers (#9002)
    • feat: add basename support for data routers (#9026)
    • ci: simplify dist/ directory for CJS/ESM only (#9017)
    • fix: Fix trailing slash behavior on pathless routing when using a basename (#9045)
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Jun 22, 2022)

    Patch Changes

    • fix: Make path resolution trailing slash agnostic (#8861)
    • fix: Additional logic fixed for relative navigation from index/pathless layout routes (#8985)
    • fix: export ActionFunctionArgs/LoaderFunctionArgs up through router packages (#8975)
    • Updated dependencies
    Source code(tar.gz)
    Source code(zip)
Owner
React Training
High-quality open source software from React Training
React Training
📋 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 32.6k Jan 8, 2023
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 Jan 7, 2023
Get started with React, Redux, and React-Router.

Deprecation Warning This project was started at the advent of the Redux ecosystem, and was intended to help users get up and running quickly. Since th

David Zukowski 10.3k Dec 23, 2022
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.5k Dec 21, 2022
Build forms in React, without the tears 😭

Build forms in React, without the tears. Visit https://formik.org to get started with Formik. Organizations and projects using Formik List of organiza

Formium 31.8k Jan 8, 2023
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 22.5k Jan 5, 2023
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 17.5k Dec 29, 2022
A React utility belt for function components and higher-order components.

A Note from the Author (acdlite, Oct 25 2018): Hi! I created Recompose about three years ago. About a year after that, I joined the React team. Today,

Andrew Clark 14.8k Dec 23, 2022
A Higher Order Component using react-redux to keep form state in a Redux store

redux-form You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of Redux

Redux Form 12.6k Dec 27, 2022
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 12.1k Jan 7, 2023
Ruthlessly simple bindings to keep react-router and redux in sync

Project Deprecated This project is no longer maintained. For your Redux <-> Router syncing needs with React Router 4+, please see one of these librari

React Community 7.9k Dec 30, 2022
: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 Jan 7, 2023
A toolchain for React component styling.

Radium yarn add radium # or npm install --save radium Radium is a set of tools to manage inline styles on React elements. It gives you powerful stylin

Formidable 7.4k Jan 1, 2023
🏁 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 7.2k Jan 6, 2023
A simple library for uni-directional dataflow application architecture with React extensions inspired by Flux

RefluxJS A simple library for unidirectional dataflow architecture inspired by ReactJS Flux. Installation You can currently install the package as a n

null 5.4k Dec 21, 2022
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 6.5k Jan 5, 2023
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.3k Dec 28, 2022
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.9k Jan 4, 2023
Alibaba Group Unified Form Solution -- Support React/Vue2/Vue3

English | 简体中文 Background In React, the whole tree rendering performance problem of the form is very obvious in the controlled mode. Especially for th

Alibaba 9k Jan 8, 2023