or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

component-handles.mdgrid-virtualization.mdgrouped-lists.mdindex.mdlist-virtualization.mdtable-virtualization.md

component-handles.mddocs/

0

# Component Handles

1

2

All React Virtuoso components provide handle interfaces for programmatic control including scrolling operations, state management, and viewport queries. These handles are accessed through React refs and provide methods for external control of virtualization behavior.

3

4

## Capabilities

5

6

### VirtuosoHandle

7

8

Handle interface for the main Virtuoso list component providing comprehensive scroll control and state management.

9

10

```typescript { .api }

11

interface VirtuosoHandle {

12

/** Use this with combination with follow output if you have images loading in the list */

13

autoscrollToBottom(): void;

14

/** Obtains the internal size state of the component, so that it can be restored later */

15

getState(stateCb: StateCallback): void;

16

/** Scrolls the component with the specified amount */

17

scrollBy(location: ScrollToOptions): void;

18

/** Scrolls the item into view if necessary */

19

scrollIntoView(location: FlatScrollIntoViewLocation): void;

20

/** Scrolls the component to the specified location */

21

scrollTo(location: ScrollToOptions): void;

22

/** Scrolls the component to the specified item index */

23

scrollToIndex(location: FlatIndexLocationWithAlign | number): void;

24

}

25

26

interface FlatScrollIntoViewLocation extends ScrollIntoViewLocationOptions {

27

index: number;

28

}

29

30

interface FlatIndexLocationWithAlign extends LocationOptions {

31

index: 'LAST' | number;

32

}

33

34

interface LocationOptions {

35

align?: 'center' | 'end' | 'start';

36

behavior?: 'auto' | 'smooth';

37

offset?: number;

38

}

39

40

interface ScrollIntoViewLocationOptions {

41

align?: 'center' | 'end' | 'start';

42

behavior?: 'auto' | 'smooth';

43

calculateViewLocation?: CalculateViewLocation;

44

done?: () => void;

45

}

46

47

type StateCallback = (state: StateSnapshot) => void;

48

49

interface StateSnapshot {

50

ranges: SizeRange[];

51

scrollTop: number;

52

}

53

```

54

55

**Usage Examples:**

56

57

```typescript

58

import React from 'react';

59

import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';

60

61

function ControlledList() {

62

const virtuosoRef = React.useRef<VirtuosoHandle>(null);

63

const [items] = React.useState(

64

Array.from({ length: 10000 }, (_, i) => `Item ${i}`)

65

);

66

67

// Scroll to specific index

68

const scrollToIndex = (index: number) => {

69

virtuosoRef.current?.scrollToIndex(index);

70

};

71

72

// Smooth scroll to index with alignment

73

const smoothScrollToIndex = (index: number) => {

74

virtuosoRef.current?.scrollToIndex({

75

index,

76

align: 'center',

77

behavior: 'smooth'

78

});

79

};

80

81

// Scroll to last item

82

const scrollToEnd = () => {

83

virtuosoRef.current?.scrollToIndex('LAST');

84

};

85

86

// Smart scroll into view

87

const scrollIntoView = (index: number) => {

88

virtuosoRef.current?.scrollIntoView({

89

index,

90

behavior: 'smooth',

91

done: () => console.log('Scroll completed')

92

});

93

};

94

95

// Force scroll to bottom (useful for chat)

96

const forceScrollToBottom = () => {

97

virtuosoRef.current?.autoscrollToBottom();

98

};

99

100

// Scroll by amount

101

const scrollByAmount = (pixels: number) => {

102

virtuosoRef.current?.scrollBy({ top: pixels, behavior: 'smooth' });

103

};

104

105

// Scroll to absolute position

106

const scrollToPosition = (scrollTop: number) => {

107

virtuosoRef.current?.scrollTo({ top: scrollTop });

108

};

109

110

// Get and restore state

111

const [savedState, setSavedState] = React.useState<StateSnapshot | null>(null);

112

113

const saveState = () => {

114

virtuosoRef.current?.getState(setSavedState);

115

};

116

117

return (

118

<div>

119

<div style={{ marginBottom: '10px' }}>

120

<button onClick={() => scrollToIndex(0)}>Go to Start</button>

121

<button onClick={() => smoothScrollToIndex(500)}>Go to Middle</button>

122

<button onClick={scrollToEnd}>Go to End</button>

123

<button onClick={() => scrollIntoView(1000)}>Smart Scroll to 1000</button>

124

<button onClick={forceScrollToBottom}>Force Bottom</button>

125

<button onClick={() => scrollByAmount(200)}>Scroll Down 200px</button>

126

<button onClick={() => scrollToPosition(0)}>Reset Position</button>

127

<button onClick={saveState}>Save State</button>

128

</div>

129

130

<Virtuoso

131

ref={virtuosoRef}

132

style={{ height: '400px' }}

133

data={items}

134

restoreStateFrom={savedState}

135

itemContent={(index, item) => (

136

<div style={{ padding: '12px', borderBottom: '1px solid #eee' }}>

137

{item} (Index: {index})

138

</div>

139

)}

140

/>

141

</div>

142

);

143

}

144

```

145

146

### GroupedVirtuosoHandle

147

148

Handle interface for the GroupedVirtuoso component with additional group-aware scrolling capabilities.

149

150

```typescript { .api }

151

interface GroupedVirtuosoHandle {

152

/** Use this with combination with follow output if you have images loading in the list */

153

autoscrollToBottom(): void;

154

/** Obtains the internal size state of the component for restoration */

155

getState(stateCb: StateCallback): void;

156

/** Scrolls the component with the specified amount */

157

scrollBy(location: ScrollToOptions): void;

158

/** Scrolls the item into view if necessary with group context */

159

scrollIntoView(location: number | ScrollIntoViewLocation): void;

160

/** Scrolls the component to the specified location */

161

scrollTo(location: ScrollToOptions): void;

162

/** Scrolls the component to the specified item or group index */

163

scrollToIndex(location: IndexLocationWithAlign | number): void;

164

}

165

166

type IndexLocationWithAlign = FlatIndexLocationWithAlign | GroupIndexLocationWithAlign;

167

168

interface GroupIndexLocationWithAlign extends LocationOptions {

169

groupIndex: number;

170

}

171

172

type ScrollIntoViewLocation = FlatScrollIntoViewLocation | GroupedScrollIntoViewLocation;

173

174

interface GroupedScrollIntoViewLocation extends ScrollIntoViewLocationOptions {

175

groupIndex: number;

176

}

177

```

178

179

**Usage Example:**

180

181

```typescript

182

import React from 'react';

183

import { GroupedVirtuoso, GroupedVirtuosoHandle } from 'react-virtuoso';

184

185

function ControlledGroupedList() {

186

const groupedRef = React.useRef<GroupedVirtuosoHandle>(null);

187

188

const groups = [

189

{ name: 'Group A', items: Array.from({ length: 50 }, (_, i) => `A-${i}`) },

190

{ name: 'Group B', items: Array.from({ length: 30 }, (_, i) => `B-${i}`) },

191

{ name: 'Group C', items: Array.from({ length: 40 }, (_, i) => `C-${i}`) }

192

];

193

194

const groupCounts = groups.map(g => g.items.length);

195

const allItems = groups.flatMap(g => g.items);

196

197

// Scroll to specific group

198

const scrollToGroup = (groupIndex: number) => {

199

groupedRef.current?.scrollToIndex({

200

groupIndex,

201

align: 'start',

202

behavior: 'smooth'

203

});

204

};

205

206

// Scroll to specific item by flat index

207

const scrollToItem = (itemIndex: number) => {

208

groupedRef.current?.scrollToIndex({

209

index: itemIndex,

210

align: 'center'

211

});

212

};

213

214

// Scroll group into view

215

const scrollGroupIntoView = (groupIndex: number) => {

216

groupedRef.current?.scrollIntoView({

217

groupIndex,

218

behavior: 'smooth'

219

});

220

};

221

222

return (

223

<div>

224

<div style={{ marginBottom: '10px' }}>

225

{groups.map((group, index) => (

226

<button key={index} onClick={() => scrollToGroup(index)}>

227

Go to {group.name}

228

</button>

229

))}

230

<button onClick={() => scrollToItem(50)}>Go to Item 50</button>

231

</div>

232

233

<GroupedVirtuoso

234

ref={groupedRef}

235

style={{ height: '400px' }}

236

groupCounts={groupCounts}

237

groupContent={(index) => (

238

<div style={{

239

padding: '12px',

240

backgroundColor: '#f0f0f0',

241

fontWeight: 'bold'

242

}}>

243

{groups[index].name}

244

</div>

245

)}

246

itemContent={(index, groupIndex, item) => (

247

<div style={{ padding: '8px 16px', borderBottom: '1px solid #eee' }}>

248

{item} (Group: {groupIndex})

249

</div>

250

)}

251

data={allItems}

252

/>

253

</div>

254

);

255

}

256

```

257

258

### VirtuosoGridHandle

259

260

Handle interface for the VirtuosoGrid component providing grid-specific scrolling capabilities.

261

262

```typescript { .api }

263

interface VirtuosoGridHandle {

264

/** Scrolls the grid with the specified amount */

265

scrollBy(location: ScrollToOptions): void;

266

/** Scrolls the grid to the specified location */

267

scrollTo(location: ScrollToOptions): void;

268

/** Scrolls the grid to the specified item index */

269

scrollToIndex(location: GridIndexLocation): void;

270

}

271

272

type GridIndexLocation = FlatIndexLocationWithAlign | number;

273

```

274

275

**Usage Example:**

276

277

```typescript

278

import React from 'react';

279

import { VirtuosoGrid, VirtuosoGridHandle } from 'react-virtuoso';

280

281

function ControlledGrid() {

282

const gridRef = React.useRef<VirtuosoGridHandle>(null);

283

const items = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);

284

285

const scrollToItem = (index: number) => {

286

gridRef.current?.scrollToIndex({

287

index,

288

align: 'start',

289

behavior: 'smooth'

290

});

291

};

292

293

const jumpToTop = () => {

294

gridRef.current?.scrollTo({ top: 0, behavior: 'smooth' });

295

};

296

297

const scrollDown = () => {

298

gridRef.current?.scrollBy({ top: 300, behavior: 'smooth' });

299

};

300

301

return (

302

<div>

303

<div style={{ marginBottom: '10px' }}>

304

<button onClick={jumpToTop}>Top</button>

305

<button onClick={() => scrollToItem(100)}>Item 100</button>

306

<button onClick={() => scrollToItem(500)}>Item 500</button>

307

<button onClick={scrollDown}>Scroll Down</button>

308

</div>

309

310

<VirtuosoGrid

311

ref={gridRef}

312

style={{ height: '400px' }}

313

data={items}

314

itemContent={(index, item) => (

315

<div style={{

316

padding: '16px',

317

border: '1px solid #ddd',

318

margin: '4px',

319

textAlign: 'center'

320

}}>

321

{item}

322

</div>

323

)}

324

/>

325

</div>

326

);

327

}

328

```

329

330

### TableVirtuosoHandle

331

332

Handle interface for table virtualization components.

333

334

```typescript { .api }

335

interface TableVirtuosoHandle {

336

/** Obtains the internal size state of the component for restoration */

337

getState(stateCb: StateCallback): void;

338

/** Scrolls the table with the specified amount */

339

scrollBy(location: ScrollToOptions): void;

340

/** Scrolls the table to the specified location */

341

scrollTo(location: ScrollToOptions): void;

342

/** Scrolls the row into view if necessary */

343

scrollIntoView(location: FlatScrollIntoViewLocation | number): void;

344

/** Scrolls the table to the specified row index */

345

scrollToIndex(location: FlatIndexLocationWithAlign | number): void;

346

}

347

348

interface GroupedTableVirtuosoHandle {

349

/** Obtains the internal size state of the component for restoration */

350

getState(stateCb: StateCallback): void;

351

/** Scrolls the table with the specified amount */

352

scrollBy(location: ScrollToOptions): void;

353

/** Scrolls the table to the specified location */

354

scrollTo(location: ScrollToOptions): void;

355

/** Scrolls the item into view if necessary with group context */

356

scrollIntoView(location: ScrollIntoViewLocationOptions): void;

357

/** Scrolls the table to the specified item index */

358

scrollToIndex(location: IndexLocationWithAlign | number): void;

359

}

360

```

361

362

**Usage Example:**

363

364

```typescript

365

import React from 'react';

366

import { TableVirtuoso, TableVirtuosoHandle } from 'react-virtuoso';

367

368

function ControlledTable() {

369

const tableRef = React.useRef<TableVirtuosoHandle>(null);

370

const data = Array.from({ length: 1000 }, (_, i) => ({

371

id: i + 1,

372

name: `Row ${i + 1}`,

373

value: Math.random() * 100

374

}));

375

376

const scrollToRow = (index: number) => {

377

tableRef.current?.scrollToIndex({

378

index,

379

align: 'center',

380

behavior: 'smooth'

381

});

382

};

383

384

const scrollRowIntoView = (index: number) => {

385

tableRef.current?.scrollIntoView({

386

index,

387

behavior: 'smooth',

388

done: () => console.log(`Scrolled to row ${index}`)

389

});

390

};

391

392

const saveTableState = () => {

393

tableRef.current?.getState((state) => {

394

console.log('Table state:', state);

395

// Save state to localStorage or state management

396

});

397

};

398

399

return (

400

<div>

401

<div style={{ marginBottom: '10px' }}>

402

<button onClick={() => scrollToRow(0)}>First Row</button>

403

<button onClick={() => scrollToRow(500)}>Middle Row</button>

404

<button onClick={() => scrollRowIntoView(999)}>Last Row</button>

405

<button onClick={saveTableState}>Save State</button>

406

</div>

407

408

<TableVirtuoso

409

ref={tableRef}

410

style={{ height: '400px' }}

411

data={data}

412

fixedHeaderContent={() => (

413

<tr>

414

<th style={{ padding: '12px' }}>ID</th>

415

<th style={{ padding: '12px' }}>Name</th>

416

<th style={{ padding: '12px' }}>Value</th>

417

</tr>

418

)}

419

itemContent={(index, item) => (

420

<>

421

<td style={{ padding: '12px' }}>{item.id}</td>

422

<td style={{ padding: '12px' }}>{item.name}</td>

423

<td style={{ padding: '12px' }}>{item.value.toFixed(2)}</td>

424

</>

425

)}

426

/>

427

</div>

428

);

429

}

430

```

431

432

## Advanced Scroll Control

433

434

### Custom Scroll Calculation

435

436

Fine-tune scroll behavior with custom view location calculation.

437

438

```typescript { .api }

439

type CalculateViewLocation = (params: CalculateViewLocationParams) => IndexLocationWithAlign | null | number;

440

441

interface CalculateViewLocationParams {

442

itemBottom: number;

443

itemTop: number;

444

locationParams: {

445

align?: 'center' | 'end' | 'start';

446

behavior?: 'auto' | 'smooth';

447

} & ({ groupIndex: number } | { index: number });

448

viewportBottom: number;

449

viewportTop: number;

450

}

451

```

452

453

**Usage Example:**

454

455

```typescript

456

// Custom scroll behavior that only scrolls if item is completely out of view

457

const customScrollBehavior: CalculateViewLocation = ({

458

itemTop,

459

itemBottom,

460

viewportTop,

461

viewportBottom,

462

locationParams

463

}) => {

464

// Only scroll if item is completely out of view

465

const completelyAbove = itemBottom < viewportTop;

466

const completelyBelow = itemTop > viewportBottom;

467

468

if (completelyAbove) {

469

return { ...locationParams, align: 'start' };

470

} else if (completelyBelow) {

471

return { ...locationParams, align: 'end' };

472

}

473

474

// Item is at least partially visible, don't scroll

475

return null;

476

};

477

478

// Use in scrollIntoView

479

virtuosoRef.current?.scrollIntoView({

480

index: targetIndex,

481

calculateViewLocation: customScrollBehavior,

482

behavior: 'smooth'

483

});

484

```

485

486

### State Management

487

488

```typescript { .api }

489

interface StateSnapshot {

490

ranges: SizeRange[];

491

scrollTop: number;

492

}

493

494

interface SizeRange {

495

startIndex: number;

496

endIndex: number;

497

size: number;

498

}

499

```

500

501

**Usage Example:**

502

503

```typescript

504

function StatefulVirtuoso() {

505

const [savedState, setSavedState] = React.useState<StateSnapshot | null>(null);

506

const virtuosoRef = React.useRef<VirtuosoHandle>(null);

507

508

// Save state before navigation

509

const handleNavigation = () => {

510

virtuosoRef.current?.getState((state) => {

511

localStorage.setItem('virtuoso-state', JSON.stringify(state));

512

});

513

};

514

515

// Restore state on mount

516

React.useEffect(() => {

517

const stored = localStorage.getItem('virtuoso-state');

518

if (stored) {

519

setSavedState(JSON.parse(stored));

520

}

521

}, []);

522

523

return (

524

<Virtuoso

525

ref={virtuosoRef}

526

restoreStateFrom={savedState}

527

data={items}

528

itemContent={(index, item) => <div>{item}</div>}

529

/>

530

);

531

}

532

```

533

534

## Types

535

536

```typescript { .api }

537

interface ScrollToOptions {

538

top?: number;

539

left?: number;

540

behavior?: 'auto' | 'smooth';

541

}

542

543

enum LogLevel {

544

DEBUG,

545

INFO,

546

WARN,

547

ERROR

548

}

549

```