@@ -2,8 +2,10 @@ import React from 'react'
2
2
import { findDOMNode } from 'react-dom'
3
3
import parsePath from 'history/lib/parsePath'
4
4
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
+ }
7
9
}
8
10
9
11
const createKey = ( ) => (
@@ -19,36 +21,17 @@ const addScrollKey = (locationOrString) => {
19
21
return location
20
22
}
21
23
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
-
32
24
const RestoreWindowScroll = React . createClass ( {
33
25
34
26
propTypes : {
35
- router : React . PropTypes . object . isRequired ,
27
+ restoreScrollPosition : React . PropTypes . func . isRequired ,
36
28
location : React . PropTypes . object . isRequired
37
29
} ,
38
30
39
31
componentDidUpdate ( prevProps ) {
40
32
const { location } = this . props
41
33
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 )
52
35
}
53
36
} ,
54
37
@@ -57,20 +40,61 @@ const RestoreWindowScroll = React.createClass({
57
40
}
58
41
} )
59
42
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 ) => (
61
78
( options = { } ) => {
79
+ setManualScroll ( )
80
+
62
81
const initialScrollKey = createKey ( )
63
82
let currentScrollKey = null
64
83
65
84
const history = createHistory ( options )
66
85
86
+ ////
87
+ // `positionsByLocation` looks like this
88
+ //
89
+ // ```
67
90
// {
68
91
// [location.key]: {
69
92
// window: { scrollX, scrollY },
70
93
// [scrollKey]: { scrollTop, scrollLeft }
71
94
// },
72
95
// [location.key]: etc...
73
96
// }
97
+ // ```
74
98
const positionsByLocation = { }
75
99
const scrollers = { }
76
100
@@ -84,8 +108,8 @@ export const useHistoryRestoreScroll = (createHistory) => (
84
108
history . replace ( location )
85
109
}
86
110
87
- const registerScroller = ( scrollKey , component ) => {
88
- scrollers [ scrollKey ] = component
111
+ const registerScroller = ( scrollKey , node ) => {
112
+ scrollers [ scrollKey ] = node
89
113
}
90
114
91
115
const unregisterScroller = ( scrollKey ) => {
@@ -103,8 +127,8 @@ export const useHistoryRestoreScroll = (createHistory) => (
103
127
const { scrollY, scrollX } = window
104
128
savePosition ( 'window' , { scrollX, scrollY } )
105
129
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
108
132
savePosition ( scrollKey , { scrollTop, scrollLeft } )
109
133
}
110
134
}
@@ -125,6 +149,36 @@ export const useHistoryRestoreScroll = (createHistory) => (
125
149
return ( ) => unlisten ( ) && internalUnlisten ( )
126
150
}
127
151
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
+
128
182
return {
129
183
...history ,
130
184
listen,
@@ -133,50 +187,26 @@ export const useHistoryRestoreScroll = (createHistory) => (
133
187
restoreScroll : {
134
188
registerScroller,
135
189
unregisterScroller,
136
- getScrollerPosition
190
+ getScrollerPosition,
191
+ restoreScrollPosition
137
192
}
138
193
}
139
194
}
140
195
)
141
196
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
+ )
181
205
} )
182
206
207
+ export {
208
+ useHistoryRestoreScroll ,
209
+ useRouterRestoreScroll ,
210
+ RestoreScroll
211
+ }
212
+
0 commit comments