Declarative routing for React

Related tags

React 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!

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
  • add createModuleRoutes() utility function for lazy loading route modules

    add createModuleRoutes() utility function for lazy loading route modules

    Discussion - Demo Project

    The createModuleRoutes() utility is inspired by the Remix Route module convention. It allows a dev to provide a module function on their route that dynamically imports a route module with named exports, instead of explicitly adding those properties to the Route object.

    That is to say, it turns this:

    import Foo, { fooLoader, fooAction, FooErrorBoundary } from './pages/foo';
    
    {
      path: "foo",
      element: <Foo />,
      loader: fooLoader,
      action: fooAction,
      errorElement: <FooErrorBoundary />,
    }
    

    into this:

    {
      path: "foo",
      module: () => import('./pages/foo'),
    }
    

    Any properties set directly on the route object take precedence over module exports. So if you have specific routes you want to not lazy load the loader so it can fetch data as fast as possible, you just specify loader directly on the route alongside the module, and that will be the loader that gets invoked (the implementation won't even both trying to set up a lazy-loaded loader in that case):

    {
      path: "foo",
      module: () => import('./pages/foo'),
      loader: fooLoader,
    }
    

    The same goes for action, element

    By leveraging import() and React.lazy() the implementation is super straightforward, and practically every build tool and bundler knows how to code-split when it sees that.

    I think this could be useful for a large number of React Router users by providing a "happy path" for code-splitting and lazy loading without being too heavy-handed.

    It can also serve as a foundation for file-based routing plugins for things like Webpack/Vite/Parcel/etc.

    This gives the developer a lever to pull between:

    • bundling all your loaders in the primary chunk for fastest possible execution of data fetching, at the cost of larger bundle sizes
    • lazily loading your loader/action code along with your UI component for smallest initial bundle size at the cost of additional latency when lazy loading the route module code
    • or any configuration in between

    Which I think is very much in the Remix spirit of things :) Feedback welcome!


    PS: I know I probably left out a bunch of stuff (docs/tests/etc), if this is something y'all are interested in merging I'll be sure to flesh out this PR with all those goodies. I also have next to zero experience with React Native, so not sure if this is something useful in that space either.

    CLA Signed 
    opened by rossipedia 6
  • Improved absolute redirect url detection in actions/loaders

    Improved absolute redirect url detection in actions/loaders

    This solves the issue remix-run/remix#5002.

    With this change, we are able to redirect to URI's like mailto:[email protected] before this change it was not possible because it was interpreted as a relative path.

    The regex comes from https://stackoverflow.com/a/31991870 and should match all common absolute URLs and URIs including string starting with //.

    I tested it with in my own project and it worked like a charm!

    CLA Signed 
    opened by lkwr 3
  • SSR in >= 6.4? (Documentation outdated)

    SSR in >= 6.4? (Documentation outdated)

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

    Is or will it be possible to still Server Side Render in React Router >= 6.4?

    The documentation seems to be outdated at this moment (https://reactrouter.com/en/main/guides/ssr). The new RouterProvider/Router object does not seem to be compatible with the older 'StaticRouter'.

    Why should this feature be included?

    Not all the features of Remix might be needed, but it would still be nice to do a simple SSR, like we could in version <= 6.3.

    feature 
    opened by xriter 1
  • test(react-router-dom): streamline jsdom submitter bug workaround

    test(react-router-dom): streamline jsdom submitter bug workaround

    Work around the submitter bug in just one place, and link to my jsdom PR which will fix it, so that the workaround can be removed sooner rather than later 🤞

    This workaround refactor also establishes a pattern for other jsdom bug polyfills which will be landing in forthcoming RR PRs (the bugs aren't relevant in the current test suite, but will be in the PRs 😅)

    CLA Signed 
    opened by jenseng 4
  • History Blocking: Fix loop rendering and usePrompt

    History Blocking: Fix loop rendering and usePrompt

    Note: This should target https://github.com/remix-run/react-router/pull/9709 - but the implementation changed drastically after https://github.com/remix-run/react-router/pull/9709/commits/3545cdcc45b08b5ee5f61b37161811ce133be051 - I reviewed the changes and pulled in the bits that still work well with the previous implementation.

    This PR includes two major fixes for History Blocking that I needed to be able to continue with our React Router migration. Feel free to take them whole-sale or just pick out the pieces you like. I will say the usePrompt logic took me 4/5 days of iterating and thinking hard about the various scenarios. I tried to comment the code well, but let me know if you have any additional questions.

    Here is the behavior usePrompt ended up with - I think it's the best I could do with my approach. To reiterate the issues for what happens if you close a previous prompt with a new back-button click:

    Chrome: closes the prompt and triggers the 'shouldBlock' conditional case (window.confirm is false) BUT if it triggers another navigation that event gets dropped on the floor as there is a navigation from the back-button pending.

    Safari: closes the prompt and triggers the 'shouldBlock' conditional case (same as chrome), BUT if it triggers another navigation that event gets queued and handled in addition to the navigation event from the back-button.

    Firefox: stacks the prompts on top of each other and keeps previous prompts suspended. As the user clicks 'OK' or 'Cancel, the correct response is queued and then all prompts resolve when the final one closes, all navigation triggered seem to happen.

    FWIW I think Chrome is the most 'buggy' implementation as it calls a function and drops it on the floor with no error or warning. Both Safari and Firefox have reasonable implementations IMO.

    | prompt state | Chrome | Firefox | Safari | | ------------------- | ----------- | ---------- | --------- | | single prompt accepted | works as expected | works as expected |works as expected | | single prompt rejected | works as expected | works as expected | works as expected | | multi prompt accepted | will cancel instead| works as expected if user clicks OK on all prompts, else cancel | URL is wrong until user clicks OK and then navigates to the right place | | multi prompt rejected | works as expected | works as expected | works as expected |

    Please pull this and play around with it. AFAICT everything is working as it should, but I could easily have missed something. I think if we do end up taking this whole-sale, it would make sense to mark usePrompt and useBlocker as unstable for the first release to work out an kinks.

    Lemme know if you have any questions - I'm both here and on Discord, Develra

    opened by develra 2
  • [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
Bdc-walkthrough - An Angular Material library for displaying walk-through pop-ups and dialogs using a declarative way.

Material walk-through library An Angular Material library for displaying walk-through pop-ups and dialogs using a declarative way. Show Demo Prerequis

Broadcom Inc 65 Dec 14, 2022
Distance Matrix Routing App with Tom Tom API

Distance Matrix Routing App Have you ever wanted to build a delivery app that will calculate the shortest distance from each drop off spot? Get extra

Ania Kubow 31 Dec 13, 2022
Read Blog. This is also a practical project. Working with APIs more and Routing and many new things.

React blog This is a React blog that created with a custom API. We serve the API in our system and run blog with it. Goals of this project In this pro

AmirHossein Mohammadi 7 Jul 25, 2022
Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone, while being compatible with the newest features of React.

Recoil · Recoil is an experimental set of utilities for state management with React. Please see the website: https://recoiljs.org Installation The Rec

Facebook Experimental 18.2k Jan 8, 2023
React Starter Kit — isomorphic web app boilerplate (Node.js, Express, GraphQL, React.js, Babel, PostCSS, Webpack, Browsersync)

React Starter Kit — "isomorphic" web app boilerplate React Starter Kit is an opinionated boilerplate for web development built on top of Node.js, Expr

Kriasoft 21.7k Dec 30, 2022
📋 React Hooks for forms validation (Web + React Native)

English | 繁中 | 简中 | 日本語 | 한국어 | Français | Italiano | Português | Español | Русский | Deutsch | Türkçe Features Built with performance and DX in mind

React Hook Form 32.4k Dec 29, 2022
:black_medium_small_square:React Move | Beautiful, data-driven animations for React

React-Move Beautiful, data-driven animations for React. Just 3.5kb (gzipped)! Documentation and Examples Features Animate HTML, SVG & React-Native Fin

Steve Hall 6.5k Jan 1, 2023
React features to enhance using Rollbar.js in React Applications

Rollbar React SDK React features to enhance using Rollbar.js in React Applications. This SDK provides a wrapper around the base Rollbar.js SDK in orde

Rollbar 39 Jan 3, 2023
🎉 toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense!

toastify-react-native ?? toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense! De

Zahid Ali 29 Oct 11, 2022
Soft UI Dashboard React - Free Dashboard using React and Material UI

Soft UI Dashboard React Start your Development with an Innovative Admin Template for Material-UI and React. If you like the look & feel of the hottest

Creative Tim 182 Dec 28, 2022
A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router.

A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router. It also includes a theme switcher from light to dark mode.

Franklin Okolie 4 Jun 5, 2022
Finished code and notes from EFA bonus class on building a React project without create-react-app

React From Scratch Completed Code This is the completed code for the EFA bonus class on building a React project from scratch. Included are also markd

Conor Broaders 3 Oct 11, 2021
Free Open Source High Quality Dashboard based on Bootstrap 4 & React 16: http://dashboards.webkom.co/react/airframe

Airframe React High Quality Dashboard / Admin / Analytics template that works great on any smartphone, tablet or desktop. Available as Open Source as

Mustafa Nabavi 6 Jun 5, 2022
React tooltip is a React.JS Component that brings usefull UX and UI information in selected elements of your website.

React Tooltip ✅ React tooltip is a React.JS Component that brings usefull UX and UI information in elements of your website. Installation ⌨️ React Too

Marc Ramos 1 Dec 22, 2021
React-Mini-Projects - Simple React mini-applications

React Mini Projects A Fully Responsive React Application contain these mini apps : Todo App Movie App Budget App Flash Card App Factor App This app wa

Morteza Rezaienia 1 Jan 1, 2022
React-tutorial - A React tutorial from Udemy (Academind)

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Patrick James Nengasca 2 Mar 31, 2022
Airbnb-React - In this project, An Airbnb experience page clone is created to learn and implement React props concepts.

Create React Airbnb App In this project An airbnb experience page clone is created to learn and implement React props concepts. Objectives Learn about

Yogesh Gurjar 4 Jun 28, 2022
Vtexio-react-apps - Apps react para plafaforma VTEX.

Projeto Modal + Apps Extras Projeto modal setando cookies. Desenvolvido em React + TypeScript para aplicação em e-commerce VTEXIO. ?? Este projeto se

Marcelo 1 Jan 3, 2022
Chrome-extension-react-boilerplate - Simple Chrome extension React boilerplate.

Simple Chrome extension React boilerplate This is a simple chrome extension boilerplate made in React to use as a default structure for your future pr

Younes 6 May 25, 2022