Skip to content

Commit abb8216

Browse files
fix: Commit context together with status to avoid race condition (#6407)
1 parent 9c80d96 commit abb8216

File tree

4 files changed

+29
-39
lines changed

4 files changed

+29
-39
lines changed

packages/react-router/tests/store-updates-during-navigation.test.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
136136
// This number should be as small as possible to minimize the amount of work
137137
// that needs to be done during a navigation.
138138
// Any change that increases this number should be investigated.
139-
expect(updates).toBeGreaterThanOrEqual(11) // WARN: this is flaky, and sometimes (rarely) is 12
139+
expect(updates).toBeGreaterThanOrEqual(10) // WARN: this is flaky, and sometimes (rarely) is 12
140140
expect(updates).toBeLessThanOrEqual(13)
141141
})
142142

@@ -155,7 +155,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
155155
// This number should be as small as possible to minimize the amount of work
156156
// that needs to be done during a navigation.
157157
// Any change that increases this number should be investigated.
158-
expect(updates).toBe(5)
158+
expect(updates).toBe(4)
159159
})
160160

161161
test('sync beforeLoad', async () => {
@@ -171,7 +171,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
171171
// This number should be as small as possible to minimize the amount of work
172172
// that needs to be done during a navigation.
173173
// Any change that increases this number should be investigated.
174-
expect(updates).toBeGreaterThanOrEqual(10) // WARN: this is flaky
174+
expect(updates).toBeGreaterThanOrEqual(9) // WARN: this is flaky
175175
expect(updates).toBeLessThanOrEqual(12)
176176
})
177177

@@ -183,7 +183,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
183183
// This number should be as small as possible to minimize the amount of work
184184
// that needs to be done during a navigation.
185185
// Any change that increases this number should be investigated.
186-
expect(updates).toBeGreaterThanOrEqual(8) // WARN: this is flaky, and sometimes (rarely) is 9
186+
expect(updates).toBeGreaterThanOrEqual(6) // WARN: this is flaky, and sometimes (rarely) is 9
187187
expect(updates).toBeLessThanOrEqual(9)
188188
})
189189

@@ -225,7 +225,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
225225
// This number should be as small as possible to minimize the amount of work
226226
// that needs to be done during a navigation.
227227
// Any change that increases this number should be investigated.
228-
expect(updates).toBe(19)
228+
expect(updates).toBe(16)
229229
})
230230

231231
test('navigate, w/ preloaded & async loaders', async () => {
@@ -241,7 +241,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
241241
// This number should be as small as possible to minimize the amount of work
242242
// that needs to be done during a navigation.
243243
// Any change that increases this number should be investigated.
244-
expect(updates).toBe(9)
244+
expect(updates).toBe(7)
245245
})
246246

247247
test('navigate, w/ preloaded & sync loaders', async () => {
@@ -257,7 +257,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
257257
// This number should be as small as possible to minimize the amount of work
258258
// that needs to be done during a navigation.
259259
// Any change that increases this number should be investigated.
260-
expect(updates).toBe(8)
260+
expect(updates).toBe(6)
261261
})
262262

263263
test('navigate, w/ previous navigation & async loader', async () => {
@@ -273,7 +273,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
273273
// This number should be as small as possible to minimize the amount of work
274274
// that needs to be done during a navigation.
275275
// Any change that increases this number should be investigated.
276-
expect(updates).toBe(7)
276+
expect(updates).toBe(5)
277277
})
278278

279279
test('preload a preloaded route w/ async loader', async () => {
@@ -291,6 +291,6 @@ describe("Store doesn't update *too many* times during navigation", () => {
291291
// This number should be as small as possible to minimize the amount of work
292292
// that needs to be done during a navigation.
293293
// Any change that increases this number should be investigated.
294-
expect(updates).toBe(2)
294+
expect(updates).toBe(1)
295295
})
296296
})

packages/router-core/src/load-matches.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ const handleRedirectAndNotFound = (
139139
inner.updateMatch(match.id, (prev) => ({
140140
...prev,
141141
status,
142+
context: buildMatchContext(inner, match.index),
142143
isFetching: false,
143144
error: err,
144145
}))
@@ -693,6 +694,7 @@ const runLoader = async (
693694
inner.updateMatch(matchId, (prev) => ({
694695
...prev,
695696
error: undefined,
697+
context: buildMatchContext(inner, index),
696698
status: 'success',
697699
isFetching: false,
698700
updatedAt: Date.now(),
@@ -705,6 +707,7 @@ const runLoader = async (
705707
...prev,
706708
status: prev.status === 'pending' ? 'success' : prev.status,
707709
isFetching: false,
710+
context: buildMatchContext(inner, index),
708711
}))
709712
return
710713
}
@@ -731,6 +734,7 @@ const runLoader = async (
731734
inner.updateMatch(matchId, (prev) => ({
732735
...prev,
733736
error,
737+
context: buildMatchContext(inner, index),
734738
status: 'error',
735739
isFetching: false,
736740
}))
@@ -754,13 +758,6 @@ const loadRouteMatch = async (
754758
let loaderIsRunningAsync = false
755759
const route = inner.router.looseRoutesById[routeId]!
756760

757-
const commitContext = () => {
758-
inner.updateMatch(matchId, (prev) => ({
759-
...prev,
760-
context: buildMatchContext(inner, index),
761-
}))
762-
}
763-
764761
if (shouldSkipLoader(inner, matchId)) {
765762
if (inner.router.isServer) {
766763
return inner.router.getMatch(matchId)!
@@ -827,7 +824,6 @@ const loadRouteMatch = async (
827824
;(async () => {
828825
try {
829826
await runLoader(inner, matchId, index, route)
830-
commitContext()
831827
const match = inner.router.getMatch(matchId)!
832828
match._nonReactive.loaderPromise?.resolve()
833829
match._nonReactive.loadPromise?.resolve()
@@ -854,12 +850,6 @@ const loadRouteMatch = async (
854850
if (!loaderIsRunningAsync) match._nonReactive.loaderPromise = undefined
855851
match._nonReactive.dehydrated = undefined
856852

857-
// Commit context now that loader has completed (or was skipped)
858-
// For async loaders, this was already done in the async callback
859-
if (!loaderIsRunningAsync) {
860-
commitContext()
861-
}
862-
863853
const nextIsFetching = loaderIsRunningAsync ? match.isFetching : false
864854
if (nextIsFetching !== match.isFetching || match.invalid !== false) {
865855
inner.updateMatch(matchId, (prev) => ({

packages/solid-router/tests/store-updates-during-navigation.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
136136
// This number should be as small as possible to minimize the amount of work
137137
// that needs to be done during a navigation.
138138
// Any change that increases this number should be investigated.
139-
expect(updates).toBeGreaterThanOrEqual(11) // WARN: this is flaky, and sometimes (rarely) is 12
139+
expect(updates).toBeGreaterThanOrEqual(10) // WARN: this is flaky, and sometimes (rarely) is 12
140140
expect(updates).toBeLessThanOrEqual(13)
141141
})
142142

@@ -156,7 +156,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
156156
// that needs to be done during a navigation.
157157
// Any change that increases this number should be investigated.
158158
// Note: Solid has different update counts than React due to different reactivity
159-
expect(updates).toBe(7)
159+
expect(updates).toBe(6)
160160
})
161161

162162
test('sync beforeLoad', async () => {
@@ -173,7 +173,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
173173
// that needs to be done during a navigation.
174174
// Any change that increases this number should be investigated.
175175
// Note: Solid has different update counts than React due to different reactivity
176-
expect(updates).toBe(10)
176+
expect(updates).toBe(8)
177177
})
178178

179179
test('nothing', async () => {
@@ -226,7 +226,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
226226
// This number should be as small as possible to minimize the amount of work
227227
// that needs to be done during a navigation.
228228
// Any change that increases this number should be investigated.
229-
expect(updates).toBe(19)
229+
expect(updates).toBe(16)
230230
})
231231

232232
test('navigate, w/ preloaded & async loaders', async () => {
@@ -242,7 +242,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
242242
// This number should be as small as possible to minimize the amount of work
243243
// that needs to be done during a navigation.
244244
// Any change that increases this number should be investigated.
245-
expect(updates).toBeGreaterThanOrEqual(11) // WARN: this is flaky, and sometimes (rarely) is 12
245+
expect(updates).toBeGreaterThanOrEqual(9) // WARN: this is flaky, and sometimes (rarely) is 12
246246
expect(updates).toBeLessThanOrEqual(13)
247247
})
248248

@@ -260,7 +260,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
260260
// that needs to be done during a navigation.
261261
// Any change that increases this number should be investigated.
262262
// Note: Solid has one fewer update than React due to different reactivity
263-
expect(updates).toBe(9)
263+
expect(updates).toBe(7)
264264
})
265265

266266
test('navigate, w/ previous navigation & async loader', async () => {
@@ -276,7 +276,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
276276
// This number should be as small as possible to minimize the amount of work
277277
// that needs to be done during a navigation.
278278
// Any change that increases this number should be investigated.
279-
expect(updates).toBe(7)
279+
expect(updates).toBe(5)
280280
})
281281

282282
test('preload a preloaded route w/ async loader', async () => {
@@ -294,6 +294,6 @@ describe("Store doesn't update *too many* times during navigation", () => {
294294
// This number should be as small as possible to minimize the amount of work
295295
// that needs to be done during a navigation.
296296
// Any change that increases this number should be investigated.
297-
expect(updates).toBe(3)
297+
expect(updates).toBe(2)
298298
})
299299
})

packages/vue-router/tests/store-updates-during-navigation.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
138138
// that needs to be done during a navigation.
139139
// Any change that increases this number should be investigated.
140140
// Note: Vue has different update counts than React/Solid due to different reactivity
141-
expect(updates).toBe(33)
141+
expect(updates).toBe(27)
142142
})
143143

144144
test('redirection in preload', async () => {
@@ -157,7 +157,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
157157
// that needs to be done during a navigation.
158158
// Any change that increases this number should be investigated.
159159
// Note: Vue has different update counts than React/Solid due to different reactivity
160-
expect(updates).toBe(13)
160+
expect(updates).toBe(10)
161161
})
162162

163163
test('sync beforeLoad', async () => {
@@ -174,7 +174,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
174174
// that needs to be done during a navigation.
175175
// Any change that increases this number should be investigated.
176176
// Note: Vue has different update counts than React/Solid due to different reactivity
177-
expect(updates).toBe(31)
177+
expect(updates).toBe(25)
178178
})
179179

180180
test('nothing', async () => {
@@ -231,7 +231,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
231231
// that needs to be done during a navigation.
232232
// Any change that increases this number should be investigated.
233233
// Note: Vue has different update counts than React/Solid due to different reactivity
234-
expect(updates).toBe(47)
234+
expect(updates).toBe(38)
235235
})
236236

237237
test('navigate, w/ preloaded & async loaders', async () => {
@@ -248,7 +248,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
248248
// that needs to be done during a navigation.
249249
// Any change that increases this number should be investigated.
250250
// Note: Vue has different update counts than React/Solid due to different reactivity
251-
expect(updates).toBe(24)
251+
expect(updates).toBe(18)
252252
})
253253

254254
test('navigate, w/ preloaded & sync loaders', async () => {
@@ -265,7 +265,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
265265
// that needs to be done during a navigation.
266266
// Any change that increases this number should be investigated.
267267
// Note: Vue has different update counts than React/Solid due to different reactivity
268-
expect(updates).toBe(22)
268+
expect(updates).toBe(16)
269269
})
270270

271271
test('navigate, w/ previous navigation & async loader', async () => {
@@ -282,7 +282,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
282282
// that needs to be done during a navigation.
283283
// Any change that increases this number should be investigated.
284284
// Note: Vue has different update counts than React/Solid due to different reactivity
285-
expect(updates).toBe(18)
285+
expect(updates).toBe(12)
286286
})
287287

288288
test('preload a preloaded route w/ async loader', async () => {
@@ -301,6 +301,6 @@ describe("Store doesn't update *too many* times during navigation", () => {
301301
// that needs to be done during a navigation.
302302
// Any change that increases this number should be investigated.
303303
// Note: Vue has different update counts than React/Solid due to different reactivity
304-
expect(updates).toBe(6)
304+
expect(updates).toBe(3)
305305
})
306306
})

0 commit comments

Comments
 (0)