or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-loading.mderror-handling.mdindex.mdnavigation-links.mdpath-search-utils.mdreact-components.mdreact-hooks.mdroute-definition.mdrouter-creation.mdssr.md

react-hooks.mddocs/

0

# React Hooks

1

2

React hooks for accessing router state, navigation functions, route data, parameters, and managing router interactions. These hooks provide type-safe access to all router functionality.

3

4

## Capabilities

5

6

### Router Access Hooks

7

8

Hooks for accessing the router instance and router state.

9

10

```typescript { .api }

11

/**

12

* Access the router instance

13

* @param opts - Options for router access

14

* @returns Router instance

15

*/

16

function useRouter<TRouter extends AnyRouter = RegisteredRouter>(

17

opts?: { warn?: boolean }

18

): TRouter;

19

20

/**

21

* Subscribe to router state changes

22

* @param opts - Router state subscription options

23

* @returns Selected router state

24

*/

25

function useRouterState<

26

TRouter extends AnyRouter = RegisteredRouter,

27

TSelected = RouterState<TRouter>,

28

TStructuralSharing extends boolean = true

29

>(

30

opts?: {

31

router?: TRouter;

32

select?: (state: RouterState<TRouter>) => TSelected;

33

structuralSharing?: TStructuralSharing;

34

}

35

): UseRouterStateResult<TRouter, TSelected>;

36

```

37

38

**Usage Examples:**

39

40

```typescript

41

import { useRouter, useRouterState } from "@tanstack/react-router";

42

43

function MyComponent() {

44

// Access router instance

45

const router = useRouter();

46

47

// Subscribe to loading state

48

const isLoading = useRouterState({

49

select: (state) => state.isLoading,

50

});

51

52

// Subscribe to current location

53

const location = useRouterState({

54

select: (state) => state.location,

55

});

56

57

return (

58

<div>

59

Current path: {location.pathname}

60

{isLoading && <div>Loading...</div>}

61

</div>

62

);

63

}

64

```

65

66

### Navigation Hooks

67

68

Hooks for programmatic navigation and location access.

69

70

```typescript { .api }

71

/**

72

* Get navigation function for programmatic navigation

73

* @param defaultOpts - Default navigation options

74

* @returns Type-safe navigation function

75

*/

76

function useNavigate<

77

TRouter extends AnyRouter = RegisteredRouter,

78

TDefaultFrom extends RoutePaths<TRouter> = "/"

79

>(

80

defaultOpts?: { from?: TDefaultFrom }

81

): UseNavigateResult<TRouter, TDefaultFrom>;

82

83

/**

84

* Access current location with optional selection

85

* @param opts - Location access options

86

* @returns Current location or selected subset

87

*/

88

function useLocation<

89

TRouter extends AnyRouter = RegisteredRouter,

90

TSelected = ParsedLocation,

91

TStructuralSharing extends boolean = true

92

>(

93

opts?: {

94

select?: (location: ParsedLocation) => TSelected;

95

structuralSharing?: TStructuralSharing;

96

}

97

): UseLocationResult<TSelected>;

98

99

/**

100

* Check if browser can navigate back

101

* @returns Whether back navigation is possible

102

*/

103

function useCanGoBack(): boolean;

104

```

105

106

**Usage Examples:**

107

108

```typescript

109

import { useNavigate, useLocation, useCanGoBack } from "@tanstack/react-router";

110

111

function NavigationComponent() {

112

const navigate = useNavigate();

113

const location = useLocation();

114

const canGoBack = useCanGoBack();

115

116

// Navigate programmatically

117

const handleNavigate = () => {

118

navigate({

119

to: "/posts/$postId",

120

params: { postId: "123" },

121

search: { tab: "comments" },

122

});

123

};

124

125

// Navigate with state

126

const handleNavigateWithState = () => {

127

navigate({

128

to: "/profile",

129

state: { fromDashboard: true },

130

replace: true,

131

});

132

};

133

134

return (

135

<div>

136

<p>Current path: {location.pathname}</p>

137

<button onClick={handleNavigate}>Go to Post</button>

138

<button onClick={() => navigate({ to: -1 })} disabled={!canGoBack}>

139

Go Back

140

</button>

141

</div>

142

);

143

}

144

```

145

146

### Route Data Hooks

147

148

Hooks for accessing route-specific data, parameters, and search values.

149

150

```typescript { .api }

151

/**

152

* Access route parameters with type safety

153

* @param opts - Params access options

154

* @returns Route parameters or selected subset

155

*/

156

function useParams<

157

TRouter extends AnyRouter = RegisteredRouter,

158

TFrom extends RoutePaths<TRouter> = "/",

159

TStrict extends boolean = true,

160

TThrow extends boolean = true,

161

TSelected = ResolveParams<TRouter, TFrom>,

162

TStructuralSharing extends boolean = true

163

>(

164

opts?: {

165

from?: TFrom;

166

strict?: TStrict;

167

shouldThrow?: TThrow;

168

select?: (params: ResolveParams<TRouter, TFrom>) => TSelected;

169

structuralSharing?: TStructuralSharing;

170

}

171

): UseParamsResult<TRouter, TFrom, TStrict, TThrow, TSelected>;

172

173

/**

174

* Access search parameters with type safety

175

* @param opts - Search access options

176

* @returns Search parameters or selected subset

177

*/

178

function useSearch<

179

TRouter extends AnyRouter = RegisteredRouter,

180

TFrom extends RoutePaths<TRouter> = "/",

181

TStrict extends boolean = true,

182

TThrow extends boolean = true,

183

TSelected = InferFullSearchSchema<TRouter, TFrom>,

184

TStructuralSharing extends boolean = true

185

>(

186

opts?: {

187

from?: TFrom;

188

strict?: TStrict;

189

shouldThrow?: TThrow;

190

select?: (search: InferFullSearchSchema<TRouter, TFrom>) => TSelected;

191

structuralSharing?: TStructuralSharing;

192

}

193

): UseSearchResult<TRouter, TFrom, TStrict, TThrow, TSelected>;

194

195

/**

196

* Access loader data from route

197

* @param opts - Loader data access options

198

* @returns Loader data or selected subset

199

*/

200

function useLoaderData<

201

TRouter extends AnyRouter = RegisteredRouter,

202

TFrom extends RoutePaths<TRouter> = "/",

203

TStrict extends boolean = true,

204

TSelected = ResolveLoaderData<TRouter, TFrom>,

205

TStructuralSharing extends boolean = true

206

>(

207

opts?: {

208

from?: TFrom;

209

strict?: TStrict;

210

select?: (data: ResolveLoaderData<TRouter, TFrom>) => TSelected;

211

structuralSharing?: TStructuralSharing;

212

}

213

): UseLoaderDataResult<TRouter, TFrom, TStrict, TSelected>;

214

215

/**

216

* Access loader dependencies

217

* @param opts - Loader deps access options

218

* @returns Loader dependencies

219

*/

220

function useLoaderDeps<

221

TRouter extends AnyRouter = RegisteredRouter,

222

TFrom extends RoutePaths<TRouter> = "/",

223

TStrict extends boolean = true,

224

TSelected = ResolveLoaderDeps<TRouter, TFrom>,

225

TStructuralSharing extends boolean = true

226

>(

227

opts?: {

228

from?: TFrom;

229

strict?: TStrict;

230

select?: (deps: ResolveLoaderDeps<TRouter, TFrom>) => TSelected;

231

structuralSharing?: TStructuralSharing;

232

}

233

): UseLoaderDepsResult<TRouter, TFrom, TStrict, TSelected>;

234

235

/**

236

* Access route context

237

* @param opts - Route context access options

238

* @returns Route context or selected subset

239

*/

240

function useRouteContext<

241

TRouter extends AnyRouter = RegisteredRouter,

242

TFrom extends RoutePaths<TRouter> = "/",

243

TStrict extends boolean = true,

244

TSelected = RouteContext<TRouter, TFrom>,

245

TStructuralSharing extends boolean = true

246

>(

247

opts?: {

248

from?: TFrom;

249

strict?: TStrict;

250

select?: (context: RouteContext<TRouter, TFrom>) => TSelected;

251

structuralSharing?: TStructuralSharing;

252

}

253

): UseRouteContextResult<TRouter, TFrom, TStrict, TSelected>;

254

```

255

256

**Usage Examples:**

257

258

```typescript

259

import { useParams, useSearch, useLoaderData, useRouteContext } from "@tanstack/react-router";

260

261

function PostDetail() {

262

// Access route parameters

263

const { postId } = useParams({ from: "/posts/$postId" });

264

265

// Access search parameters with selection

266

const page = useSearch({

267

from: "/posts/$postId",

268

select: (search) => search.page || 1,

269

});

270

271

// Access loader data

272

const { post, comments } = useLoaderData({ from: "/posts/$postId" });

273

274

// Access route context

275

const user = useRouteContext({

276

select: (context) => context.user,

277

});

278

279

return (

280

<div>

281

<h1>{post.title}</h1>

282

<p>Post ID: {postId}</p>

283

<p>Page: {page}</p>

284

<p>Viewing as: {user.name}</p>

285

</div>

286

);

287

}

288

```

289

290

### Route Match Hooks

291

292

Hooks for accessing route matches and match-related functionality.

293

294

```typescript { .api }

295

/**

296

* Access route match data

297

* @param opts - Match access options

298

* @returns Route match or selected subset

299

*/

300

function useMatch<

301

TRouter extends AnyRouter = RegisteredRouter,

302

TFrom extends RoutePaths<TRouter> = "/",

303

TStrict extends boolean = true,

304

TThrow extends boolean = true,

305

TSelected = RouteMatch<TRouter, TFrom>,

306

TStructuralSharing extends boolean = true

307

>(

308

opts?: {

309

from?: TFrom;

310

strict?: TStrict;

311

shouldThrow?: TThrow;

312

select?: (match: RouteMatch<TRouter, TFrom>) => TSelected;

313

structuralSharing?: TStructuralSharing;

314

}

315

): UseMatchResult<TRouter, TFrom, TStrict, TThrow, TSelected>;

316

317

/**

318

* Access all active route matches

319

* @param opts - Matches access options

320

* @returns Array of route matches or selected subset

321

*/

322

function useMatches<

323

TRouter extends AnyRouter = RegisteredRouter,

324

TSelected = RouteMatch[],

325

TStructuralSharing extends boolean = true

326

>(

327

opts?: {

328

select?: (matches: RouteMatch[]) => TSelected;

329

structuralSharing?: TStructuralSharing;

330

}

331

): UseMatchesResult<TSelected>;

332

333

/**

334

* Access parent matches relative to current match

335

* @param opts - Parent matches access options

336

* @returns Array of parent matches or selected subset

337

*/

338

function useParentMatches<

339

TRouter extends AnyRouter = RegisteredRouter,

340

TSelected = RouteMatch[],

341

TStructuralSharing extends boolean = true

342

>(

343

opts?: {

344

select?: (matches: RouteMatch[]) => TSelected;

345

structuralSharing?: TStructuralSharing;

346

}

347

): UseMatchesResult<TSelected>;

348

349

/**

350

* Access child matches relative to current match

351

* @param opts - Child matches access options

352

* @returns Array of child matches or selected subset

353

*/

354

function useChildMatches<

355

TRouter extends AnyRouter = RegisteredRouter,

356

TSelected = RouteMatch[],

357

TStructuralSharing extends boolean = true

358

>(

359

opts?: {

360

select?: (matches: RouteMatch[]) => TSelected;

361

structuralSharing?: TStructuralSharing;

362

}

363

): UseMatchesResult<TSelected>;

364

365

/**

366

* Get function to check if routes match current location

367

* @returns Function that returns match params or false

368

*/

369

function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>(): (

370

opts: UseMatchRouteOptions<TRouter>

371

) => false | AllParams<TRouter>;

372

```

373

374

**Usage Examples:**

375

376

```typescript

377

import { useMatch, useMatches, useParentMatches, useMatchRoute } from "@tanstack/react-router";

378

379

function RouteInfo() {

380

// Access current match

381

const match = useMatch();

382

383

// Access all matches with breadcrumb info

384

const breadcrumbs = useMatches({

385

select: (matches) => matches.map(match => ({

386

id: match.id,

387

pathname: match.pathname,

388

title: match.context?.title || match.routeId,

389

})),

390

});

391

392

// Access parent matches

393

const parentMatches = useParentMatches();

394

395

// Check route matching

396

const matchRoute = useMatchRoute();

397

const isOnProfile = matchRoute({ to: "/profile" });

398

399

return (

400

<div>

401

<nav>

402

{breadcrumbs.map((crumb) => (

403

<span key={crumb.id}>{crumb.title} / </span>

404

))}

405

</nav>

406

<p>Current match: {match.routeId}</p>

407

<p>Parent matches: {parentMatches.length}</p>

408

{isOnProfile && <p>Currently on profile page</p>}

409

</div>

410

);

411

}

412

```

413

414

### Navigation Blocking Hooks

415

416

Hooks for blocking navigation based on conditions.

417

418

```typescript { .api }

419

/**

420

* Block navigation conditionally

421

* @param opts - Navigation blocking options

422

* @returns Blocker resolver if using resolver pattern

423

*/

424

function useBlocker<

425

TRouter extends AnyRouter = RegisteredRouter,

426

TWithResolver extends boolean = false

427

>(

428

opts: {

429

shouldBlockFn: ShouldBlockFn;

430

enableBeforeUnload?: boolean | (() => boolean);

431

disabled?: boolean;

432

withResolver?: TWithResolver;

433

}

434

): TWithResolver extends true ? BlockerResolver : void;

435

436

type ShouldBlockFn = (

437

fromLocation: ParsedLocation,

438

toLocation: ParsedLocation

439

) => boolean;

440

441

interface BlockerResolver {

442

status: "idle" | "blocked";

443

confirm: () => void;

444

cancel: () => void;

445

}

446

```

447

448

**Usage Examples:**

449

450

```typescript

451

import { useBlocker } from "@tanstack/react-router";

452

453

function FormWithUnsavedChanges() {

454

const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);

455

456

// Block navigation if there are unsaved changes

457

useBlocker({

458

shouldBlockFn: () => hasUnsavedChanges,

459

enableBeforeUnload: true,

460

});

461

462

// With resolver pattern

463

const blocker = useBlocker({

464

shouldBlockFn: () => hasUnsavedChanges,

465

withResolver: true,

466

});

467

468

return (

469

<form>

470

<input onChange={() => setHasUnsavedChanges(true)} />

471

472

{blocker.status === "blocked" && (

473

<div>

474

<p>You have unsaved changes. Are you sure you want to leave?</p>

475

<button onClick={blocker.confirm}>Yes, leave</button>

476

<button onClick={blocker.cancel}>Stay</button>

477

</div>

478

)}

479

</form>

480

);

481

}

482

```

483

484

### Async Data Hooks

485

486

Hooks for handling deferred promises and async data.

487

488

```typescript { .api }

489

/**

490

* Handle deferred promises with suspense

491

* @param options - Await options

492

* @returns Tuple of resolved data and promise state

493

*/

494

function useAwaited<T>(

495

options: AwaitOptions<T>

496

): [T, DeferredPromise<T>];

497

498

interface AwaitOptions<T> {

499

/** Promise to await */

500

promise: Promise<T>;

501

}

502

503

interface DeferredPromise<T> extends Promise<T> {

504

__deferredState: DeferredPromiseState<T>;

505

}

506

507

interface DeferredPromiseState<T> {

508

status: "pending" | "success" | "error";

509

data?: T;

510

error?: any;

511

}

512

```

513

514

**Usage Examples:**

515

516

```typescript

517

import { useAwaited, defer } from "@tanstack/react-router";

518

519

function AsyncDataComponent() {

520

const { deferredPosts } = useLoaderData();

521

522

try {

523

const [posts, promise] = useAwaited({ promise: deferredPosts });

524

525

return (

526

<div>

527

<h2>Posts (Status: {promise.__deferredState.status})</h2>

528

{posts.map(post => (

529

<div key={post.id}>{post.title}</div>

530

))}

531

</div>

532

);

533

} catch (promise) {

534

// This will suspend until the promise resolves

535

throw promise;

536

}

537

}

538

```

539

540

### Link Props Hook

541

542

Hook for getting link element props with all link logic applied.

543

544

```typescript { .api }

545

/**

546

* Get props for link elements with all link logic

547

* @param options - Link options

548

* @param forwardedRef - Optional forwarded ref

549

* @returns Props object for anchor element

550

*/

551

function useLinkProps<

552

TRouter extends AnyRouter = RegisteredRouter,

553

TFrom extends string = string,

554

TTo extends string | undefined = undefined,

555

TMaskFrom extends string = TFrom,

556

TMaskTo extends string = ""

557

>(

558

options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,

559

forwardedRef?: React.ForwardedRef<Element>

560

): React.ComponentPropsWithRef<"a">;

561

562

interface UseLinkPropsOptions<TRouter extends AnyRouter, TFrom extends string, TTo extends string | undefined, TMaskFrom extends string, TMaskTo extends string>

563

extends LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {

564

/** Disabled state */

565

disabled?: boolean;

566

}

567

```

568

569

**Usage Examples:**

570

571

```typescript

572

import { useLinkProps } from "@tanstack/react-router";

573

574

function CustomLink({ to, children, ...props }) {

575

const linkProps = useLinkProps({

576

to,

577

activeProps: { className: "active" },

578

preload: "intent",

579

...props,

580

});

581

582

return (

583

<a {...linkProps} className={`custom-link ${linkProps.className || ""}`}>

584

{children}

585

</a>

586

);

587

}

588

```

589

590

### Utility Hooks

591

592

Utility hooks for common React patterns and DOM interactions.

593

594

```typescript { .api }

595

/**

596

* Hook for accessing previous values across renders

597

* @param value - Current value

598

* @returns Previous value or null if no previous value

599

*/

600

function usePrevious<T>(value: T): T | null;

601

602

/**

603

* Hook for stable callback references that don't cause re-renders

604

* @param fn - Function to stabilize

605

* @returns Stable function reference

606

*/

607

function useStableCallback<T extends (...args: Array<any>) => any>(fn: T): T;

608

609

/**

610

* Hook for working with forwarded refs

611

* @param ref - Forwarded ref from React.forwardRef

612

* @returns Inner ref that can be used on DOM elements

613

*/

614

function useForwardedRef<T>(ref?: React.ForwardedRef<T>): React.RefObject<T>;

615

616

/**

617

* Hook for IntersectionObserver functionality

618

* @param ref - Ref to element to observe

619

* @param callback - Callback when intersection changes

620

* @param intersectionObserverOptions - IntersectionObserver options

621

* @param options - Hook-specific options

622

*/

623

function useIntersectionObserver<T extends Element>(

624

ref: React.RefObject<T | null>,

625

callback: (entry: IntersectionObserverEntry | undefined) => void,

626

intersectionObserverOptions?: IntersectionObserverInit,

627

options?: { disabled?: boolean }

628

): void;

629

630

/**

631

* Hook for custom element scroll restoration

632

* @param options - Scroll restoration configuration

633

* @returns Scroll restoration entry if available

634

*/

635

function useElementScrollRestoration(

636

options: (

637

| {

638

id: string;

639

getElement?: () => Window | Element | undefined | null;

640

}

641

| {

642

id?: string;

643

getElement: () => Window | Element | undefined | null;

644

}

645

) & {

646

getKey?: (location: ParsedLocation) => string;

647

}

648

): ScrollRestorationEntry | undefined;

649

```

650

651

**Usage Examples:**

652

653

```typescript

654

import {

655

usePrevious,

656

useStableCallback,

657

useForwardedRef,

658

useIntersectionObserver,

659

useElementScrollRestoration,

660

} from "@tanstack/react-router";

661

662

// Previous value tracking

663

function CounterComponent({ count }: { count: number }) {

664

const prevCount = usePrevious(count);

665

666

return (

667

<div>

668

Current: {count}, Previous: {prevCount}

669

</div>

670

);

671

}

672

673

// Stable callbacks to prevent re-renders

674

function ExpensiveComponent({ onUpdate }: { onUpdate: (data: any) => void }) {

675

const stableOnUpdate = useStableCallback(onUpdate);

676

677

// This won't cause child re-renders when onUpdate reference changes

678

return <ChildComponent onUpdate={stableOnUpdate} />;

679

}

680

681

// Forwarded refs

682

const CustomInput = React.forwardRef<HTMLInputElement>((props, ref) => {

683

const innerRef = useForwardedRef(ref);

684

685

return <input ref={innerRef} {...props} />;

686

});

687

688

// Intersection observer

689

function LazyImage({ src, alt }: { src: string; alt: string }) {

690

const [isVisible, setIsVisible] = useState(false);

691

const imgRef = useRef<HTMLImageElement>(null);

692

693

useIntersectionObserver(

694

imgRef,

695

(entry) => {

696

if (entry?.isIntersecting) {

697

setIsVisible(true);

698

}

699

},

700

{ rootMargin: "100px" }

701

);

702

703

return (

704

<img

705

ref={imgRef}

706

src={isVisible ? src : undefined}

707

alt={alt}

708

/>

709

);

710

}

711

712

// Element scroll restoration

713

function CustomScrollableComponent() {

714

const containerRef = useRef<HTMLDivElement>(null);

715

716

const scrollEntry = useElementScrollRestoration({

717

id: "custom-scrollable",

718

getElement: () => containerRef.current,

719

});

720

721

useEffect(() => {

722

if (scrollEntry && containerRef.current) {

723

containerRef.current.scrollTop = scrollEntry.scrollY;

724

}

725

}, [scrollEntry]);

726

727

return <div ref={containerRef}>...</div>;

728

}

729

```

730

731

## Types

732

733

### Hook Result Types

734

735

```typescript { .api }

736

type UseNavigateResult<TRouter extends AnyRouter, TDefaultFrom extends RoutePaths<TRouter>> =

737

<TTo extends RoutePaths<TRouter> = "/", TFrom extends RoutePaths<TRouter> = TDefaultFrom>(

738

options: NavigateOptions<TRouter, TFrom, TTo>

739

) => Promise<void>;

740

741

type UseLocationResult<TSelected> = TSelected extends ParsedLocation

742

? ParsedLocation

743

: TSelected;

744

745

type UseParamsResult<TRouter extends AnyRouter, TFrom extends RoutePaths<TRouter>, TStrict extends boolean, TThrow extends boolean, TSelected> =

746

TStrict extends false

747

? TThrow extends false

748

? TSelected | undefined

749

: TSelected

750

: TSelected;

751

752

type UseSearchResult<TRouter extends AnyRouter, TFrom extends RoutePaths<TRouter>, TStrict extends boolean, TThrow extends boolean, TSelected> =

753

TStrict extends false

754

? TThrow extends false

755

? TSelected | undefined

756

: TSelected

757

: TSelected;

758

759

type UseMatchesResult<TSelected> = TSelected;

760

```

761

762

### Hook Options Types

763

764

```typescript { .api }

765

interface UseMatchRouteOptions<TRouter extends AnyRouter = AnyRouter> {

766

to: RoutePaths<TRouter>;

767

params?: Record<string, any>;

768

search?: Record<string, any>;

769

hash?: string;

770

fuzzy?: boolean;

771

includeSearch?: boolean;

772

includeHash?: boolean;

773

}

774

```