Skip to content

Commit

Permalink
Improve skipRender fix for directional navigation introduced in v1.6.2
Browse files Browse the repository at this point in the history
  • Loading branch information
santino committed Jul 12, 2023
1 parent 7c0aa53 commit f497419
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 25 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-concurrent-router",
"version": "1.6.2",
"version": "1.6.3",
"description": "Performant routing embracing React concurrent UI patterns",
"author": "Santino Puleio",
"license": "MIT",
Expand Down
11 changes: 4 additions & 7 deletions src/__tests__/createRouter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ describe('createRouter', () => {
)
expect(locationsMatch).toHaveBeenNthCalledWith(
3,
{ pathname: 'matchedLocation', state: null },
{ pathname: 'matchedLocation' },
{ pathname: 'newLocation' },
true
)
Expand Down Expand Up @@ -321,8 +321,7 @@ describe('createRouter', () => {
expect(prepareMatch).toHaveBeenCalledTimes(2)
expect(defaultProps.history.replace).toHaveBeenCalledTimes(1)
expect(defaultProps.history.replace).toHaveBeenCalledWith({
pathname: 'matchedLocation',
state: null
pathname: 'matchedLocation'
})
expect(mockSubscribeCallback).not.toHaveBeenCalled()
})
Expand Down Expand Up @@ -380,8 +379,7 @@ describe('createRouter', () => {
}
const matchedRoute = {
pathname: 'newLocation',
params: { foo: 'bar' },
state: null
params: { foo: 'bar' }
}
const router = createRouter(defaultProps)
const mockSubscribeCallback = jest.fn()
Expand Down Expand Up @@ -410,8 +408,7 @@ describe('createRouter', () => {
skipRenderLocation
)
expect(prepareMatch).toHaveBeenCalledTimes(1)
expect(defaultProps.history.replace).toHaveBeenCalledTimes(1)
expect(defaultProps.history.replace).toHaveBeenCalledWith(matchedRoute)
expect(defaultProps.history.replace).not.toHaveBeenCalled()
expect(mockSubscribeCallback).toHaveBeenCalledTimes(1)
expect(mockSubscribeCallback).toHaveBeenCalledWith({
component: mockComponent,
Expand Down
27 changes: 10 additions & 17 deletions src/createRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const createRouter = ({
assistPrefetch = false,
awaitComponent = false,
awaitPrefetch = false,
routes,
history
history,
routes
}) => {
const routesMap = routesToMap(routes)
const entryMatch = matchRoutes(routesMap, history.location)
Expand All @@ -27,33 +27,26 @@ const createRouter = ({

// Listen for location changes, match route entry, prepare the entry and notify subscribers.
// This pattern ensures that loading (js|data) occurs outside of, and before, rendering.
history.listen(({ location }) => {
history.listen(({ location, action }) => {
if (locationsMatch(currentEntry.location, location, true)) return // still on the same route

// skip render must not affect directional (backward/forward) navigation
const skipRender = location.state && location.state.skipRender && action !== 'POP'
const match = matchRoutes(routesMap, location)
// skip render is meant to be for current navigation action only and must not affect future backward/forward navigation
const { skipRender, ...locationState } = location.state || {}
const useLocation = {
...match.location,
state: Object.keys(locationState).length ? locationState : null
}
const locationHasMatch = locationsMatch(useLocation, location, true)
const nextEntry = skipRender
? {
...currentEntry,
location: useLocation,
location: match.location,
params: match.params,
skipRender: true
skipRender
}
: prepareMatch(match, assistPrefetch, awaitPrefetch)

if (skipRender || !locationHasMatch) {
// When skipping render we need to override history entry to not break directional navigation (forward/backward). OR
// Requested route had redirectRules that have been applied, hence
if (!locationsMatch(match.location, location, true)) {
// requested route had redirectRules that have been applied, hence
// the actual destination is not the requested location; update history
history.replace(useLocation)
return history.replace(match.location)
}
if (!locationHasMatch) return // if redirectRules are aplied we don't notify subscribers

currentEntry = nextEntry
subscribers.forEach(callback => callback(nextEntry))
Expand Down

0 comments on commit f497419

Please sign in to comment.