[React] React Virtual
// Window large lists with react-virtual // http://localhost:3000/isolated/final/04.js import React from 'react' import {useVirtual} from 'react-virtual' import {useCombobox} from '../use-combobox' import {getItems} from '../workerized-filter-cities' import {useAsync, useForceRerender} from '../utils' const getVirtualRowStyles = ({size, start}) => ({ position: 'absolute', top: 0, left: 0, width: '100%', height: size, transform: `translateY(${start}px)`, }) function Menu({ items, getMenuProps, getItemProps, highlightedIndex, selectedItem, listRef, virtualRows, totalHeight, }) { return ( <ul {...getMenuProps({ref: listRef})}> <li style={{height: totalHeight}} /> // The reason here add a li is tell react virtual, the total height of the items, so the scolling bar can display correct size {virtualRows.map(({index, size, start}) => { const item = items[index] if (!item) return null return ( <ListItem key={item.id} getItemProps={getItemProps} item={item} index={index} isSelected={selectedItem?.id === item.id} isHighlighted={highlightedIndex === index} style={getVirtualRowStyles({size, start})} > {item.name} </ListItem> ) })} </ul> ) } function ListItem({ getItemProps, item, index, isHighlighted, isSelected, style, ...props }) { return ( <li {...getItemProps({ index, item, style: { backgroundColor: isHighlighted ? 'lightgray' : 'inherit', fontWeight: isSelected ? 'bold' : 'normal', ...style, }, ...props, })} /> ) } function App() { const forceRerender = useForceRerender() const [inputValue, setInputValue] = React.useState('') const {data: items, run} = useAsync({data: [], status: 'pending'}) React.useEffect(() => { run(getItems(inputValue)) }, [inputValue, run]) const listRef = React.useRef() const rowVirtualizer = useVirtual({ size: items.length, parentRef: listRef, estimateSize: React.useCallback(() => 20, []), overscan: 10, }) const { selectedItem, highlightedIndex, getComboboxProps, getInputProps, getItemProps, getLabelProps, getMenuProps, selectItem, } = useCombobox({ items, inputValue, onInputValueChange: ({inputValue: newValue}) => setInputValue(newValue), onSelectedItemChange: ({selectedItem}) => alert( selectedItem ? `You selected ${selectedItem.name}` : 'Selection Cleared', ), itemToString: item => (item ? item.name : ''), scrollIntoView: () => {}, onHighlightedIndexChange: ({highlightedIndex}) => highlightedIndex !== -1 && rowVirtualizer.scrollToIndex(highlightedIndex), }) return ( <div className="city-app"> <button onClick={forceRerender}>force rerender</button> <div> <label {...getLabelProps()}>Find a city</label> <div {...getComboboxProps()}> <input {...getInputProps({type: 'text'})} /> <button onClick={() => selectItem(null)} aria-label="toggle menu"> ✕ </button> </div> <Menu items={items} getMenuProps={getMenuProps} getItemProps={getItemProps} highlightedIndex={highlightedIndex} selectedItem={selectedItem} listRef={listRef} virtualRows={rowVirtualizer.virtualItems} totalHeight={rowVirtualizer.totalSize} /> </div> </div> ) } export default App
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2018-10-23 [WASM] Create a New Rust/Webpack Project using the rust-webpack Template
2018-10-23 [Adobe Analytics] Segments types
2018-10-23 [WASM] Set up wasm-bindgen for easy Rust/JavaScript Interoperability
2016-10-23 [RxJS] Multicasting shortcuts: publish() and variants
2016-10-23 [RxJS] RefCount: automatically starting and stopping an execution
2015-10-23 [Angular 2] Inject Service
2015-10-23 [Angular 2] Use Service use Typescript