GithubHelp home page GithubHelp logo

fusionjs / fusion-plugin-react-router Goto Github PK

View Code? Open in Web Editor NEW
4.0 7.0 21.0 981 KB

Migrated to https://github.com/fusionjs/fusionjs

License: MIT License

JavaScript 98.73% Shell 1.02% Dockerfile 0.25%
fusion fusionjs

fusion-plugin-react-router's Introduction

fusion-plugin-react-router

Build status

The fusion-plugin-react-router package provides a universal router plugin for React. The plugin automatically configures a router provider to account for route prefix, routing events, hydration in bundle splitting scenarios, etc.

The package also offers components to control HTTP status server-side.


Table of contents


Installation

yarn add fusion-plugin-react-router

Usage

// src/components/root.js
import React from 'react';
import {
  Router,
  Route,
  Link,
  Switch,
  NotFound,
} from 'fusion-plugin-react-router';

const Home = () => <div>Hello</div>;
const Test = () => <div>Test</div>;
const PageNotFound = () => (
  <NotFound>
    <div>404</div>
  </NotFound>
);

const root = (
  <div>
    <ul>
      <li>
        <Link to="/">Home</Link>
      </li>
      <li>
        <Link to="/test">Test</Link>
      </li>
      <li>
        <Link to="/404">404</Link>
      </li>
    </ul>
    <Switch>
      <Route exact path="/" component={Home} />
      <Route exact path="/test" component={Test} />
      <Route component={PageNotFound} />
    </Switch>
  </div>
);
export default root;

Setup

// src/main.js
import App from 'fusion-react';
import Router from 'fusion-plugin-react-router';
import UniversalEvents, {
  UniversalEventsToken,
} from 'fusion-plugin-universal-events';
import root from './components/root';

export default function start(App) {
  const app = new App(root);
  app.register(Router);
  app.register(UniversalEventsToken, UniversalEvents);
  return app;
}

API

Registration API

Plugin
import Router from 'fusion-plugin-react-router';

The plugin.

RouterToken
import {RouterToken} from 'fusion-plugin-react-router';

A token for registering the router plugin on. You only need to register the plugin on this token if another plugin depends on receiving the history object.

RouterProviderToken
import {RouterProviderToken} from 'fusion-plugin-react-router';

An optional dependency of this plugin, used to replace the routing provider. Defaults to import {Router} from react-router-dom. This is necessary for integrating with connected-react-router.

UniversalEventsToken
import {UniversalEventsToken} from 'fusion-plugin-universal-events';

The universal events plugin. Optional.

Provide the UniversalEventsToken when you would like to emit routing events for data collection.


Routing Events and Timing Metrics

Router will emit the following events/metrics via the universal events plugin if provided:

Server-side routing metrics via events
  • 'pageview:server'
    • page: string - (1)The path of an exact match, or (2)ctx.path.
    • title: string - (1)props.trackingId provided by <Route>, or (2)the path of an exact match, or (3)ctx.path.
    • status: number - HTTP status of the response
    • timing: number - Milliseconds. The time since the request received till routed by this plugin.
  • 'render:server'
    • page: string - (1)The path of an exact match, or (2)ctx.path.
    • title: string - (1)props.trackingId provided by <Route>, or (2)the path of an exact match, or (3)ctx.path.
    • status: number - HTTP status of the response
    • timing: number - Milliseconds. The execution time of renderer.
Browser routing events
  • 'pageview:browser'
    • page: string - (1)The path of an exact match, or (2)ctx.path.
    • title: string - (1)props.trackingId provided by <Route>, or (2)the path of an exact match, or (3)ctx.path.

Accessing History

This plugin provides an API to access the history object.

import {createPlugin} from 'fusion-core';
import RouterPlugin, {RouterToken} from 'fusion-plugin-react-router';

app.register(RouterToken, RouterPlugin);
app.register(createPlugin({
  deps: {
    router: RouterToken,
  },
  middleware: ({router}) => (ctx, next) => {
    const {history} = router.from(ctx);
    // ...
    return next();
  }
}));

Router

Configures a router and acts as a React context provider for routing concerns. The plugin already provides <Router> in the middleware for your application.

import {Router} from 'fusion-plugin-react-router';

<Router
  location={...}
  basename={...}
  context={...}
  onRoute={...}
>{child}</Router>
  • location: string - Required. The current pathname. Should be ctx.url in a Fusion plugin, or req.url in the server or location.pathname in the client
  • basename: string - Optional. Defaults to ''. A route prefix.
  • context: {setCode: (string) => void} - Optional.
    • setCode: (string) => void - Called when <Status /> is mounted. Provides an HTTP status code.
  • onRoute: ({page: string, title: string}) => void - Optional. Called when a route change happens. Provides a pathname and a title.
  • child: React.Element - Required.

Route

Defines what gets rendered for a given route. Multiple routes can be rendered at the same time if they exist outside a Switch component.

import {Router, Route} from 'fusion-plugin-react-router';

<Router>
  <Route exact component={component} path={...} trackingId={...}>{children}</Route>
</Router>

See the react-router documentation for <Route>

  • trackingId: string - Optional. To set an analytical name for the route, and make it the first candidate to determine payload.title when emitting routing events.

Link

Similar to <a>, creates a link that routes using history.pushState rather than a page change.

import {Router, Link} from 'fusion-plugin-react-router';

<Router>
  <Link to="{...}">{children}</Link>
</Router>;

See the react-router documentation for <Link>.

Switch

Renders the first child Route that matches the path.

import {Router, Switch} from 'fusion-plugin-react-router';

<Router>
  <Switch>{children}</Switch>
</Router>;
  • children: React.Children<Route> - React children must be Route components.

See the react-router documentation for <Switch>.

Status

Signals to the Router context that an HTTP status change is required.

import {Router, Route, Status} from 'fusion-plugin-react-router';

<Router>
  <Route component={() => <Status code={...}>{child}</Status>} />
</Router>
  • code: number - A HTTP Status code to be used if this component is mounted. The status code is sent to a context.setCode call in Router
  • child: React.Element - A React element

NotFound

Equivalent to <Status code={404}></Status>

import {Router, Route, NotFound} from 'fusion-plugin-react-router';

<Router>
  <Route component={() => <NotFound>{child}</NotFound>} />
</Router>;
  • child: React.Element - A React element

Redirect

Signals to the Router context to navigate to a new location.

import {Router, Route, Redirect} from 'fusion-plugin-react-router';

<Router>
  <Route component={() => <Redirect to="/">{child}</Redirect>} />
</Router>;
  • to: string|object - Required. A URL or location to redirect to.
  • push: boolean - Optional. When true, redirecting will push a new entry onto the history instead of replacing the current one.
  • code: number - Optional. A HTTP Status code to be used if this component is mounted.

BrowserRouter

A <Router> that uses the HTML5 history API to keep your UI in sync with the URL.. This is a re-export of React Router's BrowserRouter (from react-router-dom)

import {BrowserRouter} from 'fusion-plugin-react-router';

See the react-router-dom documentation for <BrowserRouter>.

HashRouter

A <Router> that uses window.location.hash to keep your UI in sync with the URL. This is a re-export of React Router's HashRouter (from react-router-dom)

import {HashRouter} from 'fusion-plugin-react-router';

See the react-router-dom documentation for <HashRouter>.

MemoryRouter

A <Router> that keeps the history of your "URL" in memory (does not read or write to the address bar). This is a re-export of React Router's MemoryRouter

import {MemoryRouter} from 'fusion-plugin-react-router';

See the react-router-dom documentation for <MemoryRouter>.

withRouter

Exposes match, location and history properties of the React Router history object as props. This is a re-export of React Router's withRouter.

import {withRouter} from 'fusion-plugin-react-router';

See the react-router documentation for withRouter().

matchPath

Programmatic API to run React Router's route matching algorithm. This is a re-export of React Router's matchPath.

import {matchPath} from 'fusion-plugin-react-router';

See the react-router documentation for matchPath().

fusion-plugin-react-router's People

Contributors

albertywu avatar alexmsmithca avatar brendean avatar chrisdothtml avatar conradreuter avatar dennisgl avatar ganemone avatar kevingrandon avatar lhorie avatar nadiia avatar rajeshsegu avatar renovate-bot avatar renovate[bot] avatar rtsao avatar sumanvyj avatar uberopensourcebot avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

fusion-plugin-react-router's Issues

Handle non object event payloads

In theory users could emit events with primitive values
for the event payload. We should only try and extend the
payload if it is a truthy object.

Unable to style Link components with styletron

I'm having trouble styling Link components. If you nest an anchor element or anchor component, Fusion will create another anchor instead of rendering one anchor. If you pass the Link component into styletron's withStyle, Fusion crashes.

Is there a way to style Links with styletron? I'd prefer to avoid using inline style and nesting a random element for the purposes of styling.

Fix routePrefix behavior now that we are stripping the routePrefix on the server side

Type of issue

Bug

Description

When fusion-core was updated to strip the routePrefix from ctx, the router plugin was never updated to handle this behavior.

Current behavior

Links and route matching don't work as expected.

Expected behavior

Links and route matching should work with the routePrefix.

Steps to reproduce

  1. run a Fusion.js application with the ROUTE_PREFIX environment variable set
  2. add some <Route> components and <Link> components

MemoryRouter does not provide onRoute context

Type of issue

Bug

Description

MemoryRouter does not provide onRoute into child context
Besides it would be nice to be able to override onRoute with some mock function

Current behavior

When using MemoryRouter for UnitTesting it fails with following error:
TypeError: context.onRoute is not a function

Expected behavior

Should not fails on this step

Steps to reproduce

run following test snippet:

    const component = mount(
      <MemoryRouter initialEntries={['/test']}>
        <Route path="/test" render={() => <div>Test</div>} />
      </MemoryRouter>
    );

    expect(component.find('div').text()).toBe('Test');

Your environment

  • fusion-plugin-react-router version: 1.2.0

  • Node.js version (node --version): 8.14

  • npm version (npm --version): 6.4.1

  • Operating System: OSX

Unable to use `render` prop for `Route`

Type of issue

Feature request

Description

The render prop is the suggested approach for passing props to a Route from a parent component but fusion-plugin-react-router does not allow this property.

Current behavior

When passing the prop render to the Route component an error is thrown 'Cannot pass render function to tracking route'.

Expected behavior

Should be able to pass render to a Route

Your environment

  • fusion-plugin-react-router version: 1.0.4

Support server-side route redirects to external url

Type of issue

Feature request

Description

There seems to be no way to set up redirects (302s) to external urls. I understand this might be to keep consistent behavior with react-router v4's browser redirect behavior. Perhaps we can offer an <ExternalRedirect> component in fusion-plugin-react-router to workaround this?
Alternatively, if there's some way of doing this otherwise, please document it.

Current behavior

Right now, in order to set up an external redirect route, I'm doing this. This method is clearly sub-optimal since the browser is loading the page with a null component just to redirect (and there's no way to leverage 302 status code here):

    <Route
      path={`/go-to-google`}
      render={() => {
        if (__BROWSER__) {
          window.location.href = 'https://www.google.com';
        }
        return null;
      }}
    />

Expected behavior

Support a syntax like:

    <Route
      path={`/go-to-google`}
      render={() => <Redirect to={"https://www.google.com"} />}
    />

Add Token dependencies to readme

Problem/Rationale

Documentation regarding Fusion API is out of date given recent changes to leverage new Dependency Injection architecture.

Solution/Change/Deliverable

Update documentation

Status component only renders first child

Type of issue

Bug

Description

When rendering the Status component on the server if multiple children are passed in only the first is rendered.

Current behavior

Only first child is rendered

Expected behavior

All children should render

Your environment

  • fusion-plugin-react-router version: 1.5.3-alpha.0

Only emit render and pageview events

The upstream and downstream timing events should probably be handled
by some standard stats library, not the router. It does make sense for
the router to emit render/pageview stats, but not more generic stats like
upstream and downstream.

Fix server side redirects

Server side redirects are setting the status
code correctly, but are not adding the Location
header. We should use ctx.redirect

Redirect component doesn't work in browser

Type of issue

Bug

Description

On the browser the Redirect component will cause an exception

Current behavior

Exception is thrown

Expected behavior

Should work on browser and server

Steps to reproduce

  1. Render Redirect component in the browser
  2. See the error: 'checkPropTypes.js:19 Warning: Failed context type: The context router is marked as required in Redirect, but its value is undefined.'

Your environment

  • fusion-plugin-react-router version: 1.5.0-1

Use scoped emitter for page view stats

Type of issue

Feature request

Description

Instead of using the globally scoped event emitter using an emitter scoped to the request should allow us to log events with context specific details (actual path and headers from the request). This would also require the context object being passed into the emit call.

Current behavior

pageview:server is emitted on the global event bus and does not include context.

Expected behavior

pageview:server is emitted on a event bus scoped to an individual request and includes the context.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.