Giter VIP home page Giter VIP logo

react-router-scroll's Introduction

react-router-scroll Travis npm

React Router scroll management.

react-router-scroll is a React Router middleware that adds scroll management using scroll-behavior. By default, the middleware adds browser-style scroll behavior, but you can customize it to scroll however you want on route transitions.

This library does not currently support React Router v4, because React Router v4 has no concept of router middlewares. See ongoing discussion in #52. For an interim solution for just scrolling to top on navigation, see the React Router documentation on scroll restoration.

Usage

import { applyRouterMiddleware, browserHistory, Router } from 'react-router';
import { useScroll } from 'react-router-scroll';

/* ... */

ReactDOM.render(
  <Router
    history={browserHistory}
    routes={routes}
    render={applyRouterMiddleware(useScroll())}
  />,
  container
);

Guide

Installation

$ npm i -S react react-dom react-router
$ npm i -S react-router-scroll

Basic usage

Apply the useScroll router middleware using applyRouterMiddleware, as in the example above.

Custom scroll behavior

You can provide a custom shouldUpdateScroll callback as an argument to useScroll. This callback is called with the previous and the current router props.

The callback can return:

  • a falsy value to suppress updating the scroll position
  • a position array of x and y, such as [0, 100], to scroll to that position
  • a string with the id or name of an element, to scroll to that element
  • a truthy value to emulate the browser default scroll behavior
useScroll((prevRouterProps, { location }) => (
  !prevRouterProps || location.pathname !== prevRouterProps.location.pathname
));

useScroll((prevRouterProps, { routes }) => {
  if (routes.some(route => route.ignoreScrollBehavior)) {
    return false;
  }

  if (routes.some(route => route.scrollToTop)) {
    return [0, 0];
  }

  return true;
});

You can customize useScroll even further by providing a configuration object with a createScrollBehavior callback that creates the scroll behavior object. This allows using a custom subclass of ScrollBehavior from scroll-behavior with custom logic. When using a configuration object, you can specify the shouldUpdateScroll callback as above under the shouldUpdateScroll key.

useScroll({
  createScrollBehavior: (config) => new MyScrollBehavior(config),
  shouldUpdateScroll,
});

Scrolling elements other than window

Use <ScrollContainer> in components rendered by a router with the useScroll middleware to manage the scroll behavior of elements other than window. Each <ScrollContainer> must be given a unique scrollKey, and can be given an optional shouldUpdateScroll callback that behaves as above.

import { ScrollContainer } from 'react-router-scroll';

function Page() {
  /* ... */

  return (
    <ScrollContainer
      scrollKey={scrollKey}
      shouldUpdateScroll={shouldUpdateScroll}
    >
      <MyScrollableComponent />
    </ScrollContainer>
  );
}

<ScrollContainer> does not support on-the-fly changes to scrollKey or to the DOM node for its child.

Notes

Minimizing bundle size

If you are not using <ScrollContainer>, you can reduce your bundle size by importing the useScroll module directly.

import useScroll from 'react-router-scroll/lib/useScroll';

Server rendering

Do not apply the useScroll middleware when rendering on a server. You may use <ScrollContainer> in server-rendered components; it will do nothing when rendering on a server.

react-router-scroll's People

Contributors

adriantoine avatar dependabot[bot] avatar ide avatar mesoptier avatar seidtgeist avatar taion 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  avatar  avatar  avatar  avatar

react-router-scroll's Issues

scroll to element

Hello and I apologize if this is a stupid question but would it be possible to accept a target element to scroll to instead of an array?

If not, then would it be possible to define value types for those array values (i.e. pixel vs em), or is that an equally silly question?

Bug with anchors

Simple to reproduce

You can reproduce locally by doing

git clone https://github.com/MoOx/phenomic.git
cd phenomic
npm install
npm run docs-start

The doc will start & open locally.

Tell me if you need more (I made this issue really quickly as I am busy, sorry).

Can't resolve 'history/lib/DOMStateStorage' after update

Hi! I just updated and I am receiving this error:

./~/react-router-scroll/lib/StateStorage.js Module not found: Error: Can't resolve 'history/lib/DOMStateStorage' in '/home/anaibol/Workspace/fr/node_modules/react-router-scroll/lib' resolve 'history/lib/DOMStateStorage' in '/home/anaibol/Workspace/fr/node_modules/react-router-scroll/lib' Parsed request is a module using description file: /home/anaibol/Workspace/fr/node_modules/react-router-scroll/package.json (relative path: ./lib) Field 'browser' doesn't contain a valid alias configuration after using description file: /home/anaibol/Workspace/fr/node_modules/react-router-scroll/package.json (relative path: ./lib) resolve as module

Manage async transitions

Hello!

I'm trying to get this library work with a React Router middleware, react-router-redial, that fetches data and delays rendering of the new renderProps until all async work has been completed. Similar in concept to async-props.

I know that this is something this lib does not manage today as described in #44.

With async data fetching this would be expected – the scroll update happens when the router finishes; it has no way to know about your async data dependencies

My question is what a recommended strategy here would be if one wants and needs to mange this. After reading through scroll-behavior I understand it as this type of logic should not be in that repo, given that async functionality was added and then removed.

This can be managed in the projects current form by either using the shouldUpdateScroll and this.updateScroll in project land or by using this.context.scrollBehavior.scrollBehavior.updateScroll in the middleware that wants to support react-router-scroll. Maybe there is some other ways as well?

Is this the recommended way of doing this, by manage this outside of this lib, or is it something that could be added to this lib to make this easier and better?

about example

Can you show a few examples?I'm still wondering about the function of it. thank you.

Question: Subscribe to Scroll Position

We have need to actively receive the scroll position from the window in order to transform our navigation bar. How would one subscribe to the store created by this library so that when the window position changes my component can receive the position as a prop or context.

React router v4 support

Error occurs Can't resolve history/lib/DOMStateStorage for History v4.x which is used in React router v4, is there a v4 branch for this compatibility ?

Ability to scroll a target div instead of window

Our application is a fixed size, with an internal div using overflow: scroll.

This means we aren't able to scroll to top, as the current implementation of scroll-behavior assumes you are scrolling the window.

I have created a modified version where you are able to pass a target id through to scroll-behavior and instead scroll the target.

It is a pretty rough implementation. We are targeting an id with getElementById as its faster, however it could easily be changed to use querySelector and allow targeting by anything.

Just wondering if this would be useful to others? And their opinions on the best way to go about it.

You can have a look the hacky way I implemented on this gist.

(Main changes are Lines 107-114 and 172-179 of scroll-behavior.js)

useScroll is not a function runtime error

I have a weird behavior with your function:

the code below gives me a runtime error

strangest thing that I console.log the typeof useScroll:
typeof useScroll: function

but straight after this log I get:

Uncaught TypeError: (0 , _nmi.useScroll)(...) is not a function
    at Object.<anonymous> (index.js:24)
    at __webpack_require__ (bootstrap b5993f9…:555)
    at fn (bootstrap b5993f9…:86)
    at Object.<anonymous> (bootstrap b5993f9…:578)
    at __webpack_require__ (bootstrap b5993f9…:555)
    at bootstrap b5993f9…:578
    at bootstrap b5993f9…:578
(anonymous) @ index.js:24
__webpack_require__ @ bootstrap b5993f9…:555
fn @ bootstrap b5993f9…:86
(anonymous) @ bootstrap b5993f9…:578
__webpack_require__ @ bootstrap b5993f9…:555
(anonymous) @ bootstrap b5993f9…:578
(anonymous) @ bootstrap b5993f9…:578

My code:

import {
  React, // eslint-disable-line no-unused-vars

  // react-dom
  render,

  // react-router-redux
  syncHistoryWithStore,

  // react-router
  browserHistory,
  applyRouterMiddleware,

  // react-router-scroll
  useScroll
} from './nmi'

import AppRouter from './router/index'

import store from './store/index'

console.log('typeof useScroll: ', typeof useScroll)

const scrollHistory = useScroll(() => browserHistory)()

const history = syncHistoryWithStore(scrollHistory, store, {
  selectLocationState: state => state.get('routing').toObject()
})

export const init = ({ containerId, store, history }) => {
  if (!containerId) {
    console.error('There are containerId')
    return false
  }

  render(
    <AppRouter
      store={store}
      history={history}
      render={applyRouterMiddleware(useScroll())}
    />
    , document.getElementById(containerId)
  )
}

init({
  containerId: 'root',
  store,
  history
})

Support history 4.0.0

Module not found: Error: Cannot resolve module 'history/lib/Actions
Module not found: Error: Cannot resolve module 'history/lib/DOMStateStorage'

Update history package version

Hello, History package has a major version, could we have updated the peerDependencies to "history": "^2.0.0 || ^3.0.0 || ^4.0.0",

thanks

Flickers

Using exactly as described in the readme. On navigation there is a subtle flicker on the top of the page, about 400px. Makes this unusable for me! Appears in safari and chrome, didn't test in firefox. Recorded my screen to make sure I wasn't imagining.

Incompatible with history v4

After upgrading to v4.2.0 (or even 4.0.0) of history, I get the following error messages when gulping:
Watchify error: Error: Cannot find module 'history/lib/DOMStateStorage' from 'C:\whatever\node_modules\scroll-behavior\lib'
Watchify error: Error: Cannot find module 'history/lib/Actions' from 'C:\whatever\node_modules\scroll-behavior\lib'

Publish ES6 code to npm as well

Put it under "jsnext:main" in package.json so tree shaking works out of the box without having to do do an import from /lib. Happy to send a PR for this if it makes sense.

Cannot resolve module 'fbjs/lib/warning'

I'm trying to use this package, but I'm getting this error message on import

webpack-dev-server.js:1 ./~/react-scrollchor/lib/animatescroll.js Module not found: Error: Cannot resolve module 'fbjs/lib/warning'

im running
node v4.4.5
react: 15.2.0,
react-router: 2.4.1,
webpack: 1.12.9
webpack-dev-server: 1.14.0

v0.4.0 doesn't work with webpack 2

scroll-behavior v0.9.0 has the entry "module": "es/index.js" in package.json, which is great for webpack 2. But react-router-scroll v0.4.0 doesn't.

So now, here with webpack v2.1.0-beta.25, I'm getting this error:
Uncaught (in promise) TypeError: _scrollBehavior2.default is not a constructor

That's because webpack 2 resolves scroll-behavior with ES6 imports by its own way and react-router-scroll with common JS require's tries to use babel's logic.

So this import in src/ScrollBehaviorContext.js:

import ScrollBehavior from 'scroll-behavior';

needs to be rolled back to:

import ScrollBehavior from 'scroll-behavior/lib/ScrollBehavior';

Or, as a better solution, to offer also the es/ modules like scroll-behavior does.

Scrolls to top on #hash change

Take out the plugin, link to an id on the page, it works. Add this back, it will scroll up instead of to the id. I'll look into it myself but I wanted to post this so it's known first.

shouldUpdateScroll has no previous props on initial load

I've tried the example from the docs:

useScroll(({ location: prevLocation }, { location }) => (
  location.pathname !== prevLocation.pathname
))

But, on first load (initial page load), there is no prevProps object, so I have to do this:

useScroll((prevProps, nextProps) => (
  prevProps && prevProps.location.pathname !== nextProps.location.pathname
))

Am I missing something?

Security Error

Any ideas? Was on http

SecurityError: The operation is insecure.
  at sessionStorage (~/history/lib/DOMStateStorage.js:28)
  at this (~/react-router-scroll/lib/StateStorage.js:23)
  at this (~/scroll-behavior/lib/index.js:211)
  at _saveWindowPosition (~/scroll-behavior/lib/index.js:74)
  at this (raven.js:389:34)
...
(1 additional frame(s) were not displayed)

integration with react-router-relay

Is it possible to scroll only after relay has finished loading?

I can get it to work but it's a hack:

useScroll((prevRouterProps, props) => {
  if (!props.queryAggregator.readyState.done) {
    return false;
  }
  return true;
})

...

const render = ({ done }) => {
  if (done) {
    if (typeof window !== 'undefined') {
      window.scrollTo(0, 0);
    }
  }
}

...
<Route ... render={render} />

Perform the scroll operation ourselves so that we can smooth scroll

Hello,

First of all I don't know if this is the right repository to create this issue or if scroll-behaviour was the right one, but since I'm using react-router-scroll I've decided to start the thread here.

As you might know, there's a native API to perform smooth scrolling, with a polyfil for older browsers.
See: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior and https://drafts.csswg.org/cssom-view/#dictdef-scrolltooptions

At the moment, this library uses scrollTo(x, y) but I would like to use scrollTo({ left: x, top: y, behavior: 'smooth' }). react-router-scroll and scroll-behavior could accept an option (e.g.: updateScrollPos) which is a function that receives the x and y values and its role is to update the scroll position. Its default value would be the current behavior.

Thoughts?

Can we scroll some other element instead of Window?

Sorry if I've missed this somewhere. Our page layout has a fixed sidebar and content section. The content element contains the page content and this is the element that scrolls.

Can I define the scroll container element to be something other than "window"?

Triggering a scroll to top after requests have finished for the next route

The ux I am wanting to achieve is to show a loading indicator over the current route contents while kicking off the data fetching for the next route. I have a component in my tree that when it receives new props, it does this, it blocks the new children from rendering until requests are finished. however, the page scrolls to the top first. if I return false from the callback shouldUpdateScroll, is it possible to then update the scroll later on?

update peer dependency

Will you please release a new version ?

- [email protected] node_modules/history
- [email protected] node_modules/react-router
npm WARN [email protected] requires a peer of history@^2.0.0 || ^3.0.0 but none was installed.
npm WARN [email protected] requires a peer of react-router@^2.3.0 || ^3.0.0 but none was installed.
[email protected] /workspace/git.domain.com/namespace/bo-logic
└─┬ [email protected] 
  └── [email protected] 

I have tested it and it work great.

StateStorage fails if sessionStorage is not available

Since switching to react-router-scroll, we see the following error logs in our systems.

Uncaught SecurityError: Failed to read the 'sessionStorage' property from 'Window': Access is denied for this document.
SecurityError (DOM Exception 18): The operation is insecure. (?)

I think this is related to the private mode of some browsers, but I could not reproduce the problem.
My suspicion is that StateStorage should handle errors somehow and fall back to memory or other solutions if sessionStorage does not allow access.

About the browser scroll bar

When I use the react - router, I from the list page to enter details page, when I am back, no scroll bar in the right place,Can I use the react - router - scroll to correct the browser scroll bar ?

More usecases

I think this library might be helpful to me, but I'm not sure. My use case is that when I refresh a page which has dynamic content, the scroller goes back to the top of the page and doesn't go back to its original position when the content is loaded. Is this something I can address with this library or would I need something else?

react-router v3

Would it be easy to support react-router v3? Thanks for this amazing module :)

How to apply `ignoreScrollBehavior` to Links instead of routes

I want to have control over the scroll behavior on Link level because sometimes I want the same route to scroll and sometimes I don't.

Some time ago this worked just fine, but apperently it doesn't any more.

// somewhere in a render method of some component
<Link to={{ pathname: '/some/path', state: { ignoreScrollBehavior: true } }}>
  My link
</Link>

// In my root component
<Router
  history={browserHistory}
  routes={routes}
  render={applyRouterMiddleware(useScroll(
    (prevRouterProps, { routes }) => !routes.some(
      route =>
        route.ignoreScrollBehavior ||
        (location.state && location.state.ignoreScrollBehavior)
    )
  ))}
/>

Do you have any advice in this case? I just want to scroll the window, so can't use shouldUpdateScroll right?

Great addition to the router, thanks btw 🎉 !

Breaks when using latest version of history

Hi I'm getting an exception:

ModuleNotFoundError: Module not found: Error: Cannot resolve module 'history/lib/DOMStateStorage' in node_modules/react-router-scroll/lib

When using the latest version of the history module "history": "^4.5.1"

Question: going to previous scroll position with ASYNC data

Is there anything that I can do that will force this library to wait until async data/images have loaded before trying to go to a previous scroll-position when hitting the back button. Currently if I have a previous page full of images who's data is getting pulled from an async request I just stay at the top of the page because the previous position doesn't exist when the page loads.

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.