Skip to content
Merged
567 changes: 301 additions & 266 deletions packages/react-router/tests/link.test.tsx

Large diffs are not rendered by default.

392 changes: 201 additions & 191 deletions packages/react-router/tests/useNavigate.test.tsx

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/router-core/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,7 @@ export class RouterCore<
// Resolve the next to
const nextTo = dest.to
? this.resolvePathWithBase(fromPath, `${dest.to}`)
: fromPath
: this.resolvePathWithBase(fromPath, '.')

// Resolve the next params
let nextParams =
Expand Down
3 changes: 2 additions & 1 deletion packages/router-core/tests/path.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,14 @@ describe('resolvePath', () => {
['/', '/a/b/c', './d', '/a/b/c/d'],
['/', '/a/b/c', './../d', '/a/b/d'],
['/', '/a/b/c/d', './../d', '/a/b/c/d'],
['/', '/a/b/c', '../d', '/a/b/d'],
['/', '/a/b/c', '../../d', '/a/d'],
['/', '/a/b/c', '../d', '/a/b/d'],
['/', '/a/b/c', '..', '/a/b'],
['/', '/a/b/c', '../..', '/a'],
['/', '/a/b/c', '../../..', '/'],
['/', '/a/b/c/', '../../..', '/'],
['/products', '/', '/products-list', '/products/products-list'],
['/basepath', '/products', '.', '/basepath/products'],
])('resolves correctly', (base, a, b, eq) => {
it(`Base: ${base} - ${a} to ${b} === ${eq}`, () => {
expect(resolvePath({ basepath: base, base: a, to: b })).toEqual(eq)
Expand Down
9 changes: 5 additions & 4 deletions packages/solid-router/src/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useRouter } from './useRouter'

import { useIntersectionObserver } from './utils'

import { useMatches } from './Matches'
import { useMatch } from './useMatch'
import type {
AnyRouter,
Constrain,
Expand Down Expand Up @@ -132,10 +132,11 @@ export function useLinkProps<
select: (s) => s.location.searchStr,
})

// when `from` is not supplied, use the leaf route of the current matches as the `from` location
// when `from` is not supplied, use the route of the current match as the `from` location
// so relative routing works as expected
const from = useMatches({
select: (matches) => options.from ?? matches[matches.length - 1]?.fullPath,
const from = useMatch({
strict: false,
select: (match) => options.from ?? match.fullPath,
})

const _options = () => ({
Expand Down
16 changes: 14 additions & 2 deletions packages/solid-router/src/useNavigate.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as Solid from 'solid-js'
import { useRouter } from './useRouter'
import { useMatch } from './useMatch'
import type {
AnyRouter,
FromPathOption,
Expand All @@ -14,10 +15,21 @@ export function useNavigate<
>(_defaultOpts?: {
from?: FromPathOption<TRouter, TDefaultFrom>
}): UseNavigateResult<TDefaultFrom> {
const { navigate } = useRouter()
const { navigate, state } = useRouter()

const matchIndex = useMatch({
strict: false,
select: (match) => match.index,
})

return ((options: NavigateOptions) => {
return navigate({ from: _defaultOpts?.from as any, ...options })
return navigate({
...options,
from:
options.from ??
_defaultOpts?.from ??
state.matches[matchIndex()]!.fullPath,
})
}) as UseNavigateResult<TDefaultFrom>
}

Expand Down
Loading