Code Monkey home page Code Monkey logo

react-router-last-location's Introduction

Build Status Coverage Status

react-router-last-location

  • Provides access to the last location in react + react-router (v4.x, v5.x) applications.
  • โค๏ธ Using hooks? If yes, useLastLocation.
  • ๐Ÿ’‰ Using HOC? - If yes, withLastLocation.
  • Handle redirects.
  • Support TypeScript
  • Useful for handling internal routing.
  • Easily keep your users inside your app.

Demo

Edit react-router-last-location

Note: Last location != Previous browser history state

This library only returns the location that was active right before the recent location change, during the lifetime of the current window.

This means, it is not equal to the "location you were at before navigating to this history state".

In other words, the location this library provides is not necessarily the same as the one when you click the browser's back button.

Example 1

  1. Visit /: last location = null, previous browser history state = null
  2. Visit /a: last location = /, previous browser history state = /
  3. Visit /b: last location = /a, previous browser history state = /a
  4. Reload (url will stay at /b): last location = null, previous browser history state = /a

Example 2

  1. Visit /: last location = null
  2. Visit /a: last location = /
  3. Visit /b: last location = /a
  4. Go back: last location = /b, previous browser history state = /

Example 3

  1. Visit /: last location = null
  2. Visit /a: last location = /
  3. Visit /b: last location = /a
  4. Visit /c: last location = /b
  5. Go back to /a (by selecting that state explicitly in "Go back" browser dropdown that is visible upon clicking it with right mouse button): last location = /c, previous browser history state = /

How to use?

# Please remember that you should have installed react, prop-types and react-router-dom packages
# npm install react prop-types react-router-dom --save

npm install react-router-last-location --save

If you still use v1.x.x and would like to use hook useLastLocation, please upgrade to v2.x.x version (don't worry, no breaking changes).

npm install react-router-last-location@^2.0.0
# or
npm install react-router-last-location@latest

Declare <LastLocationProvider /> inside <Router />.

index.js

import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import { LastLocationProvider } from 'react-router-last-location';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
import Logger from './components/Logger';

const App = () => (
  <Router>
    <LastLocationProvider>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/contact">Contact</Link></li>
        </ul>

        <hr />

        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />

        <hr />

        <Logger />
      </div>
    </LastLocationProvider>
  </Router>
);

render(<App />, document.getElementById('root'));

Use hook useLastLocation to get lastLocation.

./components/Logger, see example

import React from 'react';
import { useLastLocation } from 'react-router-last-location';

const Logger = () => {
  const lastLocation = useLastLocation();

  return (
    <div>
      <h2>Logger!</h2>
      <pre>
        {JSON.stringify(lastLocation)}
      </pre>
    </div>
  );
};

export default LoggerHooks;

Use HOC withLastLocation to get lastLocation prop.

./components/Logger, see example

import React from 'react';
import { withLastLocation } from 'react-router-last-location';

const Logger = ({ lastLocation }) => (
  <div>
    <h2>Logger!</h2>
    <pre>
      {JSON.stringify(lastLocation)}
    </pre>
  </div>
);

export default withLastLocation(Logger);

Use RedirectWithoutLastLocation to not store redirects as last location

import React from 'react';
import { RedirectWithoutLastLocation } from 'react-router-last-location';

const MyPage = () => (
  <RedirectWithoutLastLocation to="/" />
);

export default MyPage;

You can still use a regular <Redirect /> component from react-router.

If you do, you'll then you need to manually pass the state: { preventLastLocation: true }, like below:

import React from 'react';
import { Redirect } from 'react-router-dom';

const MyPage = () => (
  <Redirect
    to={{
      pathname: '/',
      state: { preventLastLocation: true },
    }}
  />
);

export default MyPage;

LastLocationProvider

Props

watchOnlyPathname, type: boolean, default: false

Stores the last route only when pathname has changed.

react-router-last-location's People

Contributors

hinok avatar jacobmgevans avatar joealden avatar jtomaszewski avatar juhanakristian avatar mpeyper avatar nobrayner avatar spjpgrd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-router-last-location's Issues

Build breaks with React Router 5.2

After upgrading React Router to version 5.2 my builds break.

I get the following error:

Attempted import error: 'createLocation' is not exported from 'history'.

I assume this is due to the changes in history in the latest React Router and it's usage in the file RedirectWithoutLastLocation.tsx.

ReferenceError: window is not defined in Server side rendering

Hi
Using the library, When try to build the application, which has both server side rendering as well as client side rendering, got the following issue.

...\node_modules\react-router-last-location\dist\index.js:10
[1] })(window, function(WEBPACK_EXTERNAL_MODULE__0, WEBPACK_EXTERNAL_MODULE__1, WEBPACK_EXTERNAL_MODULE__6) {
[1] ^
[1] ReferenceError: window is not defined

Kindly add the following check in index.js => typeof window != "undefined" ? window : ''

So that it will work without any issues in ssr based application.

Cannot find module './withLastLocation'

Following error occurs after updating to the current 2.0.0 version. Project uses the current create-react-app package:

node_modules/react-router-last-location/dist/index.d.ts:1:57 - error TS2307: Cannot find module './withLastLocation'.

1 import withLastLocation, { WithLastLocationProps } from './withLastLocation';

Compatible with react-router-dom 5.x.x?

I just upgraded one of my projects from React Router DOM 4.x.x to 5.x.x, and it appears the peerDependency specified by this package needs 4.x.x - just curious if there's been any effort in testing the compatibility there?

Warning: <BrowserRouter> ignores the history prop

This annoying warning is popping up, with react 17.0.2 and react-router-dom 5.2.0
It all works fine, and is a great little package but yeah, any ideas of a workaround to get rid of the warning?

Typically this is what I'm working with:

import { BrowserRouter, Route } from "react-router-dom";
import { LastLocationProvider } from "react-router-last-location";
 <BrowserRouter>
  <LastLocationProvider>
    <Route>
      ...

I've tried this, as some people have suggested, but it's the same result unfortunately:

import { BrowserRouter, Route } from "react-router-dom";
import { LastLocationProvider } from "react-router-last-location";
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
 <BrowserRouter history={history}>
  <LastLocationProvider>
    <Route>
      ...

Perhaps it's just something that'll be fixed in due course or even some issue with react-router-dom? Who knows, but a cheeky workaround would be handy

Support React 17+

Hi,

It would be nice to support React 17+.

  "peerDependencies": {
    "prop-types": "^15.6.0",
    "react": "^15.5.4 || ^16.0.0 || ^17.0.0",
    "react-dom": "^15.5.4 || ^16.0.0 || ^17.0.0",
    "react-router-dom": "^4.1.1 || ^5.0.1"
  },

Thanks.

Doesn't work for reload

If the current route was A and a reload happens on route A and then user moves to route B then last route comes as null instead of A.

utility-types is missing in peer dependencies

Hello :)

In the current 2.0.0-beta.1 you are using utility-types, which is only used as dev-dependency. Please consider to move it in the peer-dependency or dependency config in the package json.

Following error occurs otherwise:

TypeScript error in /app/frontend/node_modules/react-router-last-location/dist/withLastLocation.d.ts(7,186):
Cannot find module 'utility-types'.  TS2307
5 |     lastLocation: ReturnType<typeof getLastLocation>;
6 | }
7 | declare const withLastLocation: <WrappedProps extends WithLastLocationProps>(WrappedComponent: React.ComponentType<WrappedProps>) => React.ComponentClass<Pick<Pick<WrappedProps, import("utility-types").SetDifference<keyof WrappedProps, "history" | "location" | "match" | "staticContext" | "lastLocation">> & RouteComponentProps<{}, import("react-router").StaticContext, any>, Exclude<import("utility-types").SetDifference<keyof WrappedProps, "history" | "location" | "match" | "staticContext" | "lastLocation">, "history" | "location" | "match" | "staticContext">>, any>;

How to retrieve the last `match` object

Hello everybody,

Is there any way I could retrieve the last match ({path, url})?
I want to know which is the matched route (likes "/users/:userId/cart") of the last location, so I can know what is the matched page of the last location.

Thank you for your time

FaCC, FaPC, Component injection

Possible APIs

Function as Child Component

<div>
  <LastLocation>
    {(lastLocation) => (
      <div>Last location was: {lastLocation.pathname}</div>
    )}
  </LastLocation>
</div>

Function as Prop Component

const renderLastLocation = (lastLocation) => (
  <div>Last location was: {lastLocation.pathname}</div>
);

<div>
  <LastLocation renderLastLocation={renderLastLocation} />
</div>

Component injection

const MyComponent = ({ lastLocation }) => (
  <div>Last location was: {lastLocation.pathname}</div>
);

<div>
  {# Like <Route component={MyComponent} ...> in react-router #}
  <LastLocation component={MyComponent} />
</div>

Inspiration

Variable '_default' implicitly has an 'any' type

Following error occurs after updating to the current 2.0.0 version during tsc --noEmit. The project uses the current create-react-app package:

node_modules/react-router-last-location/dist/LastLocationProvider.d.ts:10:15 - error TS7005: Variable '_default' implicitly has an 'any' type.
  declare const _default;

Missing type dependency

I was getting the following error when running tsc --project tsconfig.json after adding react-router-last-location.

$ tsc --project tsconfig.json
node_modules/react-router-last-location/dist/LastLocationProvider.d.ts:14:179 - error TS2694: Namespace '"/Users/sidecar/repos/connect-ui/node_modules/@types/react-router/index"' has no exported member 'WithRouterStatics'.

14 }, "watchOnlyPathname">, "location" | "history" | "match" | "staticContext" | "children" | "watchOnlyPathname">, "children" | "watchOnlyPathname">, any> & import("react-router").WithRouterStatics<React.ComponentClass<Pick<Pick<Pick<Props, "location" | "history" | "match" | "staticContext" | "children">, "location" | "history" | "match" | "staticContext" | "children"> & Pick<{
                                                                                                                                                                                     ~~~~~~~~~~~~~~~~~

node_modules/react-router-last-location/dist/withLastLocation.d.ts:7:482 - error TS2694: Namespace '"/Users/sidecar/repos/connect-ui/node_modules/@types/react-router/index"' has no exported member 'WithRouterStatics'.

7 declare const withLastLocation: <WrappedProps extends WithLastLocationProps>(WrappedComponent: React.ComponentType<WrappedProps>) => React.ComponentClass<import("react-router").Omit<Pick<WrappedProps, import("./types").SetDifference<keyof WrappedProps, "location" | "lastLocation" | "history" | "match" | "staticContext">> & RouteComponentProps<{}, import("react-router").StaticContext, any>, "location" | "history" | "match" | "staticContext"> & {}, any> & import("react-router").WithRouterStatics<React.FunctionComponent<Pick<WrappedProps, import("./types").SetDifference<keyof WrappedProps, "location" | "lastLocation" | "history" | "match" | "staticContext">> & RouteComponentProps<{}, import("react-router").StaticContext, any>>>;

The fix was to update @types/react-router to 5.0.3.

peerDependencies & testing-library for 2.0.1 in package.json are different in github from npm

Hi Dawid,

I am using React 17 and the peerDependencies in package.json from here (github) is including it, but the one published in npm registry no (even if they have the same 2.0.1 version).

It will be great to have a new version published in npm registry which also supports React 17 via peerDependencies.

Also you can use the bellow declaration to reduce the peerDependencies:

"peerDependencies": {
    "prop-types": "^15.6.0",
    "react": ">=15.5.4",
    "react-dom": ">=15.5.4",
    "react-router-dom": ">=4.1.1"
},

Many thanks,
Iulian

Nice module

This module does exactly what I was looking for.

Thanks !

Provide type definitions

This repo has no .d.ts to provide better Typescript support. Definitely Typed doesn't have one either, so it would be nice if it was included in the project.

This isn't only useful for Typescript, it's also used by many IDEs to provide autocomplete suggestions and improve the experience.

Doesn't account for redirects.

Using the library, I noticed this doesn't account for any redirects.

For example I'm on / and goto /profile but I get redirected to /profile/hosting.

I have a back button that does goBack() which goes back to / but I'd like the link to reflect that which only reflects /profile.

If I wasn't clear the flow should be:
/ -> /profile redirect to /profile/hosting -> /
not
/ -> /profile redirect to /profile/hosting -> /profile
for the to prop.

How it can prevent from leaving app with goBack?

The description states: Easily prevent leaving your app by users.

As history.goBack also updates the lastLocation, I don't know if to show the history back button in UI.

Can I really use this library to prevent leaving my app by history.goBack?

preventLastLocation does not work correctly

Hi,

I have just installed lib into my project and I can't make preventLastLocation working.

below is my render code:

 return (
        <NavLink
            className={props.isActiveChild ? `${props.className} active` :  props.className}
            activeClassName="active"
            to={{
                pathname: `/${language}/${props.to}`,
                state: {
                    preventLastLocation: true
                },
            }}
            id={props.id}
        >
            {props.children}
        </NavLink>
    );

You can check it here that preventLastLocation does not work
https://codesandbox.io/s/typescript-react-router-last-location-9xwoi

Versions:

    "connected-react-router": "^6.3.1",
    "react-router": "^4.3.1",
    "react-router-dom": "^4.3.1",
    "react-router-last-location": "^2.0.1",

Add support React@^16.0.0

Hi, @hinok!

Thanks for your work on this package. I use it for one of my projects. Very neat!

However, I'm going to update my project's dependency to react@^16.0.0. If I do that, I will receive peerDependency of react@^15.5.4 warnings on my console, although so far, I haven't seen issues.

React 16 has been out for a while now and react-router already supports it via react@>=15, so is there any chance that this package will receive a dependency update? Do I need to help?

Converting the tests from Enzyme to Testing Library.

Hi ๐Ÿ‘‹

I recognized your library when looking for a solution that allows me to check the previous pathname. ๐Ÿ˜

I saw that you guys are currently using Enzyme, which itself seems to be blocking the support of React 17+.

I and many friends are a part of the Open Source Raid Guild, a group that supports OSS projects. ๐Ÿ’™

Many of us work together on one large PR. ๐Ÿค“

We would fork your project to our Github Team and work on our fork, and communicate with some of the maintainers closely over at Discord.

Read more about us: https://github.com/OpenSourceRaidGuild/tutorial-quest#hi-wave-welcome-to-the-open-source-raid-guild-crossed_swords

Our discord server: https://discord.gg/JczjG8su

Let us know if you've any questions, and feel free to join the Discord already, even if it is just a question. ๐Ÿฅณ

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.