@@ -93,6 +93,14 @@ const createIntersectionObserver = (el, cb) => {
93
93
return { instance : io , el }
94
94
}
95
95
96
+ function GatsbyLinkLocationWrapper ( props ) {
97
+ return (
98
+ < Location >
99
+ { ( { location } ) => < GatsbyLink { ...props } _location = { location } /> }
100
+ </ Location >
101
+ )
102
+ }
103
+
96
104
class GatsbyLink extends React . Component {
97
105
constructor ( props ) {
98
106
super ( props )
@@ -108,23 +116,35 @@ class GatsbyLink extends React.Component {
108
116
this . handleRef = this . handleRef . bind ( this )
109
117
}
110
118
119
+ _prefetch ( ) {
120
+ let currentPath = window . location . pathname
121
+
122
+ // reach router should have the correct state
123
+ if ( this . props . _location && this . props . _location . pathname ) {
124
+ currentPath = this . props . _location . pathname
125
+ }
126
+
127
+ const rewrittenPath = rewriteLinkPath ( this . props . to , currentPath )
128
+ const newPathName = parsePath ( rewrittenPath ) . pathname
129
+
130
+ // Prefech is used to speed up next navigations. When you use it on the current navigation,
131
+ // there could be a race-condition where Chrome uses the stale data instead of waiting for the network to complete
132
+ if ( currentPath !== newPathName ) {
133
+ ___loader . enqueue ( newPathName )
134
+ }
135
+ }
136
+
111
137
componentDidUpdate ( prevProps , prevState ) {
112
138
// Preserve non IO functionality if no support
113
139
if ( this . props . to !== prevProps . to && ! this . state . IOSupported ) {
114
- ___loader . enqueue (
115
- parsePath ( rewriteLinkPath ( this . props . to , window . location . pathname ) )
116
- . pathname
117
- )
140
+ this . _prefetch ( )
118
141
}
119
142
}
120
143
121
144
componentDidMount ( ) {
122
145
// Preserve non IO functionality if no support
123
146
if ( ! this . state . IOSupported ) {
124
- ___loader . enqueue (
125
- parsePath ( rewriteLinkPath ( this . props . to , window . location . pathname ) )
126
- . pathname
127
- )
147
+ this . _prefetch ( )
128
148
}
129
149
}
130
150
@@ -148,10 +168,7 @@ class GatsbyLink extends React.Component {
148
168
if ( this . state . IOSupported && ref ) {
149
169
// If IO supported and element reference found, setup Observer functionality
150
170
this . io = createIntersectionObserver ( ref , ( ) => {
151
- ___loader . enqueue (
152
- parsePath ( rewriteLinkPath ( this . props . to , window . location . pathname ) )
153
- . pathname
154
- )
171
+ this . _prefetch ( )
155
172
} )
156
173
}
157
174
}
@@ -181,70 +198,68 @@ class GatsbyLink extends React.Component {
181
198
partiallyActive,
182
199
state,
183
200
replace,
201
+ _location,
184
202
/* eslint-enable no-unused-vars */
185
203
...rest
186
204
} = this . props
205
+
187
206
if ( process . env . NODE_ENV !== `production` && ! isLocalLink ( to ) ) {
188
207
console . warn (
189
208
`External link ${ to } was detected in a Link component. Use the Link component only for internal links. See: https://gatsby.dev/internal-links`
190
209
)
191
210
}
192
211
212
+ const prefixedTo = rewriteLinkPath ( to , _location . pathname )
213
+ if ( ! isLocalLink ( prefixedTo ) ) {
214
+ return < a href = { prefixedTo } { ...rest } />
215
+ }
216
+
193
217
return (
194
- < Location >
195
- { ( { location } ) => {
196
- const prefixedTo = rewriteLinkPath ( to , location . pathname )
197
- return isLocalLink ( prefixedTo ) ? (
198
- < Link
199
- to = { prefixedTo }
200
- state = { state }
201
- getProps = { getProps }
202
- innerRef = { this . handleRef }
203
- onMouseEnter = { e => {
204
- if ( onMouseEnter ) {
205
- onMouseEnter ( e )
206
- }
207
- ___loader . hovering ( parsePath ( prefixedTo ) . pathname )
208
- } }
209
- onClick = { e => {
210
- if ( onClick ) {
211
- onClick ( e )
212
- }
213
-
214
- if (
215
- e . button === 0 && // ignore right clicks
216
- ! this . props . target && // let browser handle "target=_blank"
217
- ! e . defaultPrevented && // onClick prevented default
218
- ! e . metaKey && // ignore clicks with modifier keys...
219
- ! e . altKey &&
220
- ! e . ctrlKey &&
221
- ! e . shiftKey
222
- ) {
223
- e . preventDefault ( )
224
-
225
- let shouldReplace = replace
226
- const isCurrent =
227
- encodeURI ( prefixedTo ) === window . location . pathname
228
- if ( typeof replace !== `boolean` && isCurrent ) {
229
- shouldReplace = true
230
- }
231
- // Make sure the necessary scripts and data are
232
- // loaded before continuing.
233
- window . ___navigate ( prefixedTo , {
234
- state,
235
- replace : shouldReplace ,
236
- } )
237
- }
238
-
239
- return true
240
- } }
241
- { ...rest }
242
- />
243
- ) : (
244
- < a href = { prefixedTo } { ...rest } />
245
- )
218
+ < Link
219
+ to = { prefixedTo }
220
+ state = { state }
221
+ getProps = { getProps }
222
+ innerRef = { this . handleRef }
223
+ onMouseEnter = { e => {
224
+ if ( onMouseEnter ) {
225
+ onMouseEnter ( e )
226
+ }
227
+ ___loader . hovering ( parsePath ( prefixedTo ) . pathname )
228
+ } }
229
+ onClick = { e => {
230
+ if ( onClick ) {
231
+ onClick ( e )
232
+ }
233
+
234
+ if (
235
+ e . button === 0 && // ignore right clicks
236
+ ! this . props . target && // let browser handle "target=_blank"
237
+ ! e . defaultPrevented && // onClick prevented default
238
+ ! e . metaKey && // ignore clicks with modifier keys...
239
+ ! e . altKey &&
240
+ ! e . ctrlKey &&
241
+ ! e . shiftKey
242
+ ) {
243
+ e . preventDefault ( )
244
+
245
+ let shouldReplace = replace
246
+ const isCurrent = encodeURI ( prefixedTo ) === _location . pathname
247
+
248
+ if ( typeof replace !== `boolean` && isCurrent ) {
249
+ shouldReplace = true
250
+ }
251
+ // Make sure the necessary scripts and data are
252
+ // loaded before continuing.
253
+ window . ___navigate ( prefixedTo , {
254
+ state,
255
+ replace : shouldReplace ,
256
+ } )
257
+ }
258
+
259
+ return true
246
260
} }
247
- </ Location >
261
+ { ...rest }
262
+ />
248
263
)
249
264
}
250
265
}
@@ -263,7 +278,7 @@ const showDeprecationWarning = (functionName, altFunctionName, version) =>
263
278
)
264
279
265
280
export default React . forwardRef ( ( props , ref ) => (
266
- < GatsbyLink innerRef = { ref } { ...props } />
281
+ < GatsbyLinkLocationWrapper innerRef = { ref } { ...props } />
267
282
) )
268
283
269
284
export const navigate = ( to , options ) => {
0 commit comments