Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion examples/react/start-large/src/typePrimitives.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as React from 'react'
import { Link, redirect, useNavigate } from '@tanstack/react-router'
import type {
RegisteredRouter,
Expand All @@ -20,7 +21,13 @@ export function useCustomNavigate<TRouter extends RegisteredRouter, TOptions>(
): void
export function useCustomNavigate(options: ValidateNavigateOptions): void {
const navigate = useNavigate()
navigate(options)

const useIsomorphicLayoutEffect =
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect

useIsomorphicLayoutEffect(() => {
navigate(options)
}, [navigate, options])
}

export function MyLink<TRouter extends RegisteredRouter, TOptions>(
Expand Down
6 changes: 5 additions & 1 deletion examples/solid/start-large/src/typePrimitives.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Link, redirect, useNavigate } from '@tanstack/solid-router'
import { onMount } from 'solid-js'
import type {
RegisteredRouter,
ValidateFromPath,
Expand All @@ -21,7 +22,10 @@ export function useCustomNavigate<TRouter extends RegisteredRouter, TOptions>(
): void
export function useCustomNavigate(options: ValidateNavigateOptions): void {
const navigate = useNavigate()
navigate(options)

onMount(() => {
navigate(options)
})
Comment on lines +26 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

Verify intended navigation behavior difference.

The Solid implementation navigates once on mount via onMount, while the React implementation (in examples/react/start-large/src/typePrimitives.tsx lines 28-30) re-navigates whenever options changes using useIsomorphicLayoutEffect with [navigate, options] dependencies.

This means:

  • Solid: Navigation occurs once after mount, regardless of subsequent options changes
  • React: Navigation re-executes whenever options reference changes

Is this behavioral difference intentional, or should the Solid version also react to options changes using createEffect?


🏁 Script executed:

#!/bin/bash
# Search for usage patterns of useCustomNavigate to understand expected behavior

# Find all usages in Solid example
rg -n "useCustomNavigate" examples/solid/

# Find all usages in React example  
rg -n "useCustomNavigate" examples/react/

# Check if there are any tests that document the expected behavior
fd -e test -e spec | xargs rg -l "useCustomNavigate|CustomNavigate" | head -10

Length of output: 1029


🏁 Script executed:

#!/bin/bash
# Examine the actual implementations in both React and Solid

echo "=== Solid typePrimitives.tsx (lines 20-30) ==="
sed -n '20,30p' examples/solid/start-large/src/typePrimitives.tsx

echo -e "\n=== React typePrimitives.tsx (lines 19-30) ==="
sed -n '19,30p' examples/react/start-large/src/typePrimitives.tsx

echo -e "\n=== Solid linkProps.tsx (lines 20-35) ==="
sed -n '20,35p' examples/solid/start-large/src/routes/linkProps.tsx

echo -e "\n=== React linkProps.tsx (lines 20-35) ==="
sed -n '20,35p' examples/react/start-large/src/routes/linkProps.tsx

Length of output: 1458



🏁 Script executed:

#!/bin/bash
# Check for any comments or documentation about this difference
# and look at the full context around these functions

echo "=== Full Solid typePrimitives.tsx function context (lines 15-35) ==="
sed -n '15,35p' examples/solid/start-large/src/typePrimitives.tsx

echo -e "\n=== Full React typePrimitives.tsx function context (lines 14-35) ==="
sed -n '14,35p' examples/react/start-large/src/typePrimitives.tsx

# Check if there's a comment/discussion in git history or PR
echo -e "\n=== Check for Solid createEffect imports ==="
grep -n "createEffect\|onMount" examples/solid/start-large/src/typePrimitives.tsx

Length of output: 1572


🏁 Script executed:

#!/bin/bash
# Check for any comments or documentation about this difference
# and look at the full context around these functions

echo "=== Full Solid typePrimitives.tsx context with imports (lines 1-40) ==="
sed -n '1,40p' examples/solid/start-large/src/typePrimitives.tsx

echo -e "\n=== Full React typePrimitives.tsx context with imports (lines 1-40) ==="
sed -n '1,40p' examples/react/start-large/src/typePrimitives.tsx

# Check if createEffect is used elsewhere in Solid examples
echo -e "\n=== Check for createEffect usage in Solid examples ==="
rg -n "createEffect" examples/solid/ | head -20

Length of output: 4531


Use createEffect with dependency tracking instead of onMount for consistency with React behavior.

The review comment accurately identifies a behavioral difference: Solid uses onMount (runs once) while React uses useIsomorphicLayoutEffect with [navigate, options] dependencies (runs when dependencies change).

In Solid, when options changes, navigation will not re-execute because onMount only runs on component initialization. This differs from React, which will re-navigate if the options reference changes. For parity with the React implementation and to follow Solid reactive patterns, use createEffect with proper dependency tracking:

const navigate = useNavigate()
createEffect(() => {
  navigate(options)
})

This ensures both frameworks have consistent behavior when options change.

🤖 Prompt for AI Agents
In examples/solid/start-large/src/typePrimitives.tsx around lines 26 to 28, the
component uses onMount to call navigate(options) which only runs once; change
this to use Solid's reactive createEffect that depends on the navigate/options
so navigation re-runs when options change. Replace the onMount call with a
createEffect that calls navigate(options) inside it (ensuring navigate and
options are captured) so behavior matches React's dependency-driven
re-navigation.

}

export function MyLink<TRouter extends RegisteredRouter, TOptions>(
Expand Down
3 changes: 2 additions & 1 deletion packages/react-router/src/useNavigate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react'
import { useLayoutEffect } from './utils'
import { useRouter } from './useRouter'
import type {
AnyRouter,
Expand Down Expand Up @@ -67,7 +68,7 @@ export function Navigate<
TMaskFrom,
TMaskTo
> | null>(null)
React.useEffect(() => {
useLayoutEffect(() => {
if (previousPropsRef.current !== props) {
navigate(props)
previousPropsRef.current = props
Expand Down
Loading