Skip to content

Commit

Permalink
feat: add useScroll, extract useElementScroll, useWindowScroll (#219)
Browse files Browse the repository at this point in the history
* feat: add useScroll, extract useElementScroll, useWindowScroll

* fix: include list postion in window scroll mode

* docs: update api

* fix: update types

* test: add simple test using windowRef, custom useScroll hook

* test: pin @testing-library/react-hooks to 5.1.3 for node10 support
  • Loading branch information
piecyk authored Dec 2, 2021
1 parent f4b62c4 commit aa8dc9c
Show file tree
Hide file tree
Showing 13 changed files with 1,236 additions and 82 deletions.
15 changes: 9 additions & 6 deletions docs/src/pages/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,6 @@ const {
- `paddingEnd: Integer`
- Defaults to `0`
- The amount of padding in pixels to add to the end of the virtual list
- `onScrollElement: React.useRef(DOMElement)`
- Optional
- Allows using a different element to bind the `onScroll` event to
- `scrollOffsetFn: Function(event?: Event) => number`
- Optional
- This function, if passed, is called on scroll to get the scroll offset rather than using `parentRef`'s `width` or `height`
- `keyExtractor: Function(index) => String | Integer`
- Optional
- This function receives the index of each item and should return the item's unique ID.
Expand All @@ -81,6 +75,15 @@ const {
- Defaults to `defaultRangeExtractor`, is exported
- **Must be memoized using `React.useCallback()`**
- This function receives visible range parameters and should return array of indexes to render
- `windowRef: React.useRef(Window)`
- Optional
- If passed, will be used as scroll container
- `useWindowObserver: Function(windowRef: React.useRef(Window), initialRect?: { width: number; height: number }) => ({ width: number; height: number })`
- Optional
- This hook, if passed, is responsible for getting `windowRef`'s dimensions, in window scroll mode
- `useScroll: Function({ parentRef; windowRef; horizontal; useObserver; useWindowObserver; initialRect }) => ({ outerSize: number; scrollOffset: number; scrollToFn: (offset: number, reason: ScrollReason) => void })`
- Optional
- This hook, if passed, is responsible for handling scroll

### Returns

Expand Down
5 changes: 5 additions & 0 deletions examples/window-scroll/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
12 changes: 12 additions & 0 deletions examples/window-scroll/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
20 changes: 20 additions & 0 deletions examples/window-scroll/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "window-scroll",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"start": "vite"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-virtual": "2.9.0"
},
"devDependencies": {
"@rollup/plugin-replace": "^3.0.0",
"@vitejs/plugin-react": "^1.0.8",
"vite": "^2.6.14"
}
}
21 changes: 21 additions & 0 deletions examples/window-scroll/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
html, body {
margin: 0px;
padding: 0px;
font-family: sans-serif;
font-size: 14px;
}

.List {
max-width: 100%;
}

.ListItemEven,
.ListItemOdd {
display: flex;
align-items: center;
justify-content: center;
}

.ListItemEven {
background-color: #e6e4dc;
}
64 changes: 64 additions & 0 deletions examples/window-scroll/src/main.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'

import { useVirtual } from 'react-virtual'

const rows = new Array(10000)
.fill(true)
.map(() => 25 + Math.round(Math.random() * 100))

function App() {
const parentRef = React.useRef(null)

const rowVirtualizer = useVirtual({
size: rows.length,
parentRef,
windowRef: React.useRef(window),
})

return (
<div>
<h1>Window scroll - demo</h1>
<div>
<div ref={parentRef} style={{ width: `100%` }}>
<div
style={{
height: `${rowVirtualizer.totalSize}px`,
width: '100%',
position: 'relative',
}}
>
{rowVirtualizer.virtualItems.map(virtualRow => (
<div
key={virtualRow.key}
ref={virtualRow.measureRef}
className={
virtualRow.index % 2 ? 'ListItemOdd' : 'ListItemEven'
}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
transform: `translateY(${virtualRow.start}px)`,
}}
>
<div style={{ height: `${rows[virtualRow.index]}px` }}>
Row {virtualRow.index}
</div>
</div>
))}
</div>
</div>
</div>
</div>
)
}

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
25 changes: 25 additions & 0 deletions examples/window-scroll/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as path from 'path'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import rollupReplace from '@rollup/plugin-replace'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
rollupReplace({
preventAssignment: true,
values: {
__DEV__: JSON.stringify(true),
'process.env.NODE_ENV': JSON.stringify('development'),
},
}),
react(),
],
resolve: process.env.USE_SOURCE
? {
alias: {
'react-virtual': path.resolve(__dirname, '../../src/index.js'),
},
}
: {},
})
Loading

1 comment on commit aa8dc9c

@vercel
Copy link

@vercel vercel bot commented on aa8dc9c Dec 2, 2021

Choose a reason for hiding this comment

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

Please sign in to comment.