Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ And if you use `npm`
```shell
npm install react-router-scroll-top --save
```

## Props
- `delay` _(number) : A delay before scroll to top function is run. Default `0`
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/ScrollToTop.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import React, { Fragment } from "react"
import { type Props } from "."

class ScrollToTop extends React.PureComponent<Props> {
static defaultProps: {
delay: 0
}

componentDidUpdate: (prevProps: Props) => void

props: Props
Expand Down
7 changes: 4 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ type Location = {

export type Props = {
children?: React$Node,
location: Location
location: Location,
delay: number
}

export const componentDidUpdate = function componentDidUpdate(
prevProps: Props
) {
const { location }: Props = this.props
const { location, delay }: Props = this.props

if (location !== prevProps.location) {
window.scrollTo(LEFT, TOP)
setTimeout(() => window.scrollTo(LEFT, TOP), delay)
}
}

Expand Down
59 changes: 55 additions & 4 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,32 @@ import { spy } from "sinon"
const TOP = 0
const LEFT = 0

const TIMEOUTS = 1
const NO_DELAY = 0
const DELAY = 1000

jest.useFakeTimers()

describe("ScrollToTop", () => {
describe("componentDidUpdate", () => {
it("scrolls window to top on location update", () => {
global.scrollTo = spy()
const prevProps = {
location: "/"
location: "/",
}
const props = {
location: "/about"
location: "/about",
}

componentDidUpdate.bind({ props })(prevProps)

expect(global.scrollTo.calledOnce).toBe(true)
expect(global.scrollTo.calledWith(TOP, LEFT)).toBe(true)
setTimeout(() => {
expect(setTimeout).toHaveBeenCalledTimes(TIMEOUTS)
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), NO_DELAY)

expect(global.scrollTo.calledOnce).toBe(true)
expect(global.scrollTo.calledWith(TOP, LEFT)).toBe(true)
}, NO_DELAY)
})

it("does not scroll window to top on same location", () => {
Expand All @@ -35,5 +46,45 @@ describe("ScrollToTop", () => {

expect(global.scrollTo.calledOnce).toBe(false)
})

it("scrolls window after given delay", () => {
global.scrollTo = spy()

const prevProps = {
location: "/"
}
const props = {
delay: DELAY,
location: "/about"
}

componentDidUpdate.bind({ props })(prevProps)

setTimeout(() => {
expect(setTimeout).toHaveBeenCalledTimes(TIMEOUTS)
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), DELAY)

expect(global.scrollTo.calledOnce).toBe(true)
expect(global.scrollTo.calledWith(TOP, LEFT)).toBe(true)
}, DELAY)
})

it("does not scroll window immediately if given delay", () => {
global.scrollTo = spy()

const prevProps = {
location: "/"
}
const props = {
delay: DELAY,
location: "/about"
}

componentDidUpdate.bind({ props })(prevProps)

setTimeout(() => {
expect(global.scrollTo.calledOnce).toBe(false)
}, NO_DELAY)
})
})
})