Skip to content

Commit 21d633c

Browse files
committed
more
1 parent 61c2163 commit 21d633c

File tree

1 file changed

+98
-68
lines changed

1 file changed

+98
-68
lines changed

modules/index.js

Lines changed: 98 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import React from 'react'
22
import { findDOMNode } from 'react-dom'
33
import parsePath from 'history/lib/parsePath'
44

5-
if (typeof window !== 'undefined' && 'scrollRestoration' in window.history) {
6-
history.scrollRestoration = 'manual'
5+
const setManualScroll = () => {
6+
if (typeof window !== 'undefined' && 'scrollRestoration' in window.history) {
7+
history.scrollRestoration = 'manual'
8+
}
79
}
810

911
const createKey = () => (
@@ -19,36 +21,17 @@ const addScrollKey = (locationOrString) => {
1921
return location
2022
}
2123

22-
export const useRouterRestoreScroll = () => ({
23-
renderRouterContext: (child, props) => (
24-
<RestoreWindowScroll
25-
router={props.router}
26-
location={props.location}
27-
children={child}
28-
/>
29-
)
30-
})
31-
3224
const RestoreWindowScroll = React.createClass({
3325

3426
propTypes: {
35-
router: React.PropTypes.object.isRequired,
27+
restoreScrollPosition: React.PropTypes.func.isRequired,
3628
location: React.PropTypes.object.isRequired
3729
},
3830

3931
componentDidUpdate(prevProps) {
4032
const { location } = this.props
4133
if (prevProps.location !== this.props.location) {
42-
if (location.action === 'PUSH' || location.action === 'REPLACE') {
43-
window.scrollTo(0, 0)
44-
} else {
45-
const { getScrollerPosition } = this.props.router.restoreScroll
46-
const position = getScrollerPosition('window')
47-
if (position) {
48-
const { scrollX, scrollY } = position
49-
window.scrollTo(scrollX, scrollY)
50-
}
51-
}
34+
this.props.restoreScrollPosition('window', location)
5235
}
5336
},
5437

@@ -57,20 +40,61 @@ const RestoreWindowScroll = React.createClass({
5740
}
5841
})
5942

60-
export const useHistoryRestoreScroll = (createHistory) => (
43+
const RestoreScroll = React.createClass({
44+
45+
contextTypes: {
46+
router: React.PropTypes.object.isRequired
47+
},
48+
49+
propTypes: {
50+
scrollKey: React.PropTypes.string.isRequired
51+
},
52+
53+
componentDidMount() {
54+
const { registerScroller } = this.context.router.restoreScroll
55+
const { scrollKey } = this.props
56+
registerScroller(scrollKey, findDOMNode(this))
57+
this.restoreScrollPosition()
58+
},
59+
60+
componentWillUnmount() {
61+
const { unregisterScroller } = this.context.router.restoreScroll
62+
const { scrollKey } = this.props
63+
unregisterScroller(scrollKey)
64+
},
65+
66+
restoreScrollPosition() {
67+
const { restoreScrollPosition } = this.context.router.restoreScroll
68+
restoreScrollPosition(this.props.scrollKey)
69+
},
70+
71+
render() {
72+
return React.Children.only(this.props.children)
73+
}
74+
75+
})
76+
77+
const useHistoryRestoreScroll = (createHistory) => (
6178
(options={}) => {
79+
setManualScroll()
80+
6281
const initialScrollKey = createKey()
6382
let currentScrollKey = null
6483

6584
const history = createHistory(options)
6685

86+
////
87+
// `positionsByLocation` looks like this
88+
//
89+
// ```
6790
// {
6891
// [location.key]: {
6992
// window: { scrollX, scrollY },
7093
// [scrollKey]: { scrollTop, scrollLeft }
7194
// },
7295
// [location.key]: etc...
7396
// }
97+
// ```
7498
const positionsByLocation = {}
7599
const scrollers = {}
76100

@@ -84,8 +108,8 @@ export const useHistoryRestoreScroll = (createHistory) => (
84108
history.replace(location)
85109
}
86110

87-
const registerScroller = (scrollKey, component) => {
88-
scrollers[scrollKey] = component
111+
const registerScroller = (scrollKey, node) => {
112+
scrollers[scrollKey] = node
89113
}
90114

91115
const unregisterScroller = (scrollKey) => {
@@ -103,8 +127,8 @@ export const useHistoryRestoreScroll = (createHistory) => (
103127
const { scrollY, scrollX } = window
104128
savePosition('window', { scrollX, scrollY })
105129
for (const scrollKey in scrollers) {
106-
const scrollerComponent = scrollers[scrollKey]
107-
const { scrollTop, scrollLeft } = findDOMNode(scrollerComponent)
130+
const scrollerNode = scrollers[scrollKey]
131+
const { scrollTop, scrollLeft } = scrollerNode
108132
savePosition(scrollKey, { scrollTop, scrollLeft })
109133
}
110134
}
@@ -125,6 +149,36 @@ export const useHistoryRestoreScroll = (createHistory) => (
125149
return () => unlisten() && internalUnlisten()
126150
}
127151

152+
const restoreWindow = (location) => {
153+
if (location.action === 'PUSH' || location.action === 'REPLACE') {
154+
window.scrollTo(0, 0)
155+
} else {
156+
const position = getScrollerPosition('window')
157+
if (position) {
158+
const { scrollX, scrollY } = position
159+
window.scrollTo(scrollX, scrollY)
160+
}
161+
}
162+
}
163+
164+
const restoreNode = (scrollKey) => {
165+
const position = getScrollerPosition(scrollKey)
166+
if (position) {
167+
const node = scrollers[scrollKey]
168+
const { scrollTop, scrollLeft } = position
169+
node.scrollTop = scrollTop
170+
node.scrollLeft = scrollLeft
171+
}
172+
}
173+
174+
const restoreScrollPosition = (key, location) => {
175+
if (key === 'window') {
176+
restoreWindow(location)
177+
} else {
178+
restoreNode(key)
179+
}
180+
}
181+
128182
return {
129183
...history,
130184
listen,
@@ -133,50 +187,26 @@ export const useHistoryRestoreScroll = (createHistory) => (
133187
restoreScroll: {
134188
registerScroller,
135189
unregisterScroller,
136-
getScrollerPosition
190+
getScrollerPosition,
191+
restoreScrollPosition
137192
}
138193
}
139194
}
140195
)
141196

142-
export const RestoreScroll = React.createClass({
143-
144-
contextTypes: {
145-
router: React.PropTypes.object.isRequired
146-
},
147-
148-
propTypes: {
149-
scrollKey: React.PropTypes.string.isRequired
150-
},
151-
152-
componentDidMount() {
153-
const { registerScroller } = this.context.router.restoreScroll
154-
const { scrollKey } = this.props
155-
registerScroller(scrollKey, this)
156-
this.restoreScrollPosition()
157-
},
158-
159-
componentWillUnmount() {
160-
const { unregisterScroller } = this.context.router.restoreScroll
161-
const { scrollKey } = this.props
162-
unregisterScroller(scrollKey)
163-
},
164-
165-
restoreScrollPosition() {
166-
const { scrollKey } = this.props
167-
const { getScrollerPosition } = this.context.router.restoreScroll
168-
const position = getScrollerPosition(scrollKey)
169-
if (position) {
170-
const node = findDOMNode(this)
171-
const { scrollTop, scrollLeft } = position
172-
node.scrollTop = scrollTop
173-
node.scrollLeft = scrollLeft
174-
}
175-
},
176-
177-
render() {
178-
return React.Children.only(this.props.children)
179-
}
180-
197+
const useRouterRestoreScroll = () => ({
198+
renderRouterContext: (child, props) => (
199+
<RestoreWindowScroll
200+
restoreScrollPosition={props.router.restoreScroll.restoreScrollPosition}
201+
location={props.location}
202+
children={child}
203+
/>
204+
)
181205
})
182206

207+
export {
208+
useHistoryRestoreScroll,
209+
useRouterRestoreScroll,
210+
RestoreScroll
211+
}
212+

0 commit comments

Comments
 (0)