Skip to content
Open
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
18 changes: 9 additions & 9 deletions src/Filler.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import ResizeObserver from 'rc-resize-observer';
import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
import * as React from 'react';

export type InnerProps = Pick<React.HTMLAttributes<HTMLDivElement>, 'role' | 'id'>;

Expand Down Expand Up @@ -69,15 +69,15 @@ const Filler = React.forwardRef(
};
}

const handleResize = ({ offsetHeight }) => {
if (offsetHeight && onInnerResize) {
onInnerResize();
}
};

return (
<div style={outerStyle}>
<ResizeObserver
onResize={({ offsetHeight }) => {
if (offsetHeight && onInnerResize) {
onInnerResize();
}
}}
>
<ResizeObserver onResize={handleResize}>
<div
style={innerStyle}
className={classNames({
Expand Down
8 changes: 2 additions & 6 deletions src/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import useOriginScroll from './hooks/useOriginScroll';
import useScrollDrag from './hooks/useScrollDrag';
import type { ScrollPos, ScrollTarget } from './hooks/useScrollTo';
import useScrollTo from './hooks/useScrollTo';
import type { ExtraRenderInfo, GetKey, RenderFunc, SharedConfig } from './interface';
import type { ExtraRenderInfo, GetKey, RenderFunc } from './interface';
import type { ScrollBarDirectionType, ScrollBarRef } from './ScrollBar';
import ScrollBar from './ScrollBar';
import { getSpinSize } from './utils/scrollbarUtil';
Expand Down Expand Up @@ -165,10 +165,6 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
setScrollMoving(false);
};

const sharedConfig: SharedConfig<T> = {
getKey,
};

// ================================ Scroll ================================
function syncScrollTop(newTop: number | ((prev: number) => number)) {
setOffsetTop((origin) => {
Expand Down Expand Up @@ -572,7 +568,7 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
offsetLeft,
setInstanceRef,
children,
sharedConfig,
getKey,
);

let componentStyle: React.CSSProperties = null;
Expand Down
37 changes: 20 additions & 17 deletions src/hooks/useChildren.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import type { RenderFunc, SharedConfig } from '../interface';
import type { RenderFunc, GetKey } from '../interface';
import { Item } from '../Item';

export default function useChildren<T>(
Expand All @@ -10,22 +10,25 @@ export default function useChildren<T>(
offsetX: number,
setNodeRef: (item: T, element: HTMLElement) => void,
renderFunc: RenderFunc<T>,
{ getKey }: SharedConfig<T>,
getKey: GetKey<T>,
) {
return list.slice(startIndex, endIndex + 1).map((item, index) => {
const eleIndex = startIndex + index;
const node = renderFunc(item, eleIndex, {
style: {
width: scrollWidth,
},
offsetX,
}) as React.ReactElement;
// The list reference may remain unchanged, but its internal data may change, which can result in different behavior compared to the previous implementation.
return React.useMemo(() => {
return list.slice(startIndex, endIndex + 1).map((item, index) => {
const eleIndex = startIndex + index;
const node = renderFunc(item, eleIndex, {
style: {
width: scrollWidth,
},
offsetX,
}) as React.ReactElement;

const key = getKey(item);
return (
<Item key={key} setRef={(ele) => setNodeRef(item, ele)}>
{node}
</Item>
);
});
const key = getKey(item);
return (
<Item key={key} setRef={(ele) => setNodeRef(item, ele)}>
{node}
</Item>
);
});
}, [list, startIndex, endIndex, setNodeRef, renderFunc, getKey, offsetX, scrollWidth]);
}
5 changes: 3 additions & 2 deletions src/hooks/useHeights.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default function useHeights<T>(
}
}

function setInstanceRef(item: T, instance: HTMLElement) {
const setInstanceRef = React.useCallback(function setInstanceRef(item: T, instance: HTMLElement) {
const key = getKey(item);
const origin = instanceRef.current.get(key);

Expand All @@ -88,11 +88,12 @@ export default function useHeights<T>(
onItemRemove?.(item);
}
}
}
}, [getKey, onItemAdd, onItemRemove]);

useEffect(() => {
return cancelRaf;
}, []);

// This is somewhat confusing: when heightsRef.current.set is called, updatedMark changes, which in turn causes heightsRef.current to also change.
return [setInstanceRef, collectHeight, heightsRef.current, updatedMark];
}
4 changes: 0 additions & 4 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ export type RenderFunc<T> = (
props: { style: React.CSSProperties; offsetX: number },
) => React.ReactNode;

export interface SharedConfig<T> {
getKey: (item: T) => React.Key;
}

export type GetKey<T> = (item: T) => React.Key;

export type GetSize = (startKey: React.Key, endKey?: React.Key) => { top: number; bottom: number };
Expand Down
57 changes: 37 additions & 20 deletions tests/props.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { mount } from 'enzyme';
import React from 'react';
import List from '../src';

describe('Props', () => {
Expand All @@ -11,30 +11,20 @@ describe('Props', () => {
}

const wrapper = mount(
<List data={[{ id: 903 }, { id: 1128 }]} itemKey={item => item.id}>
<List data={[{ id: 903 }, { id: 1128 }]} itemKey={(item) => item.id}>
{({ id }) => <ItemComponent>{id}</ItemComponent>}
</List>,
);

expect(
wrapper
.find('Item')
.at(0)
.key(),
).toBe('903');

expect(
wrapper
.find('Item')
.at(1)
.key(),
).toBe('1128');
expect(wrapper.find('Item').at(0).key()).toBe('903');

expect(wrapper.find('Item').at(1).key()).toBe('1128');
});

it('prefixCls', () => {
const wrapper = mount(
<List data={[0]} itemKey={id => id} prefixCls="prefix">
{id => <div>{id}</div>}
<List data={[0]} itemKey={(id) => id} prefixCls="prefix">
{(id) => <div>{id}</div>}
</List>,
);

Expand All @@ -44,13 +34,40 @@ describe('Props', () => {
it('offsetX in renderFn', () => {
let scrollLeft;
mount(
<List data={[0]} itemKey={id => id} prefixCls="prefix">
{(id, _, { offsetX }) => {
<List data={[0]} itemKey={(id) => id} prefixCls="prefix">
{(id, _, { offsetX }) => {
scrollLeft = offsetX;
return <div>{id}</div>}}
return <div>{id}</div>;
}}
</List>,
);

expect(scrollLeft).toEqual(0);
});

it('no unnecessary re-render', () => {
const renderItem = jest.fn();
renderItem.mockImplementation(({ id, key }) => <div key={key}>{id}</div>);

const data = [{ id: 1, key: 1 }];
function Wrapper() {
const [state, setState] = React.useState(0);

React.useEffect(() => {
setState(1);
}, []);

return (
<div>
<h1>{state}</h1>
<List data={data} itemKey="key" prefixCls="prefix">
{renderItem}
</List>
</div>
);
}
const wrapper = mount(<Wrapper />);
expect(wrapper.find('h1').text()).toBe('1');
expect(renderItem).toHaveBeenCalledTimes(1);
});
});
12 changes: 7 additions & 5 deletions tests/scroll-Firefox.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { act } from '@testing-library/react';
import { mount } from 'enzyme';
import { spyElementPrototypes } from './utils/domHook';
import React from 'react';
import List from '../src';
import isFF from '../src/utils/isFirefox';
import { spyElementPrototypes } from './utils/domHook';

function genData(count) {
return new Array(count).fill(null).map((_, index) => ({ id: String(index) }));
Expand Down Expand Up @@ -124,8 +124,10 @@ describe('List.Firefox-Scroll', () => {
const wrapper = genList({ itemHeight: 20, height: 100, data: genData(100), ref: listRef });
const ulElement = wrapper.find('ul').instance();
// scroll to bottom
listRef.current.scrollTo(99999);
jest.runAllTimers();
act(() => {
listRef.current.scrollTo(99999);
jest.runAllTimers();
});
expect(wrapper.find('ul').instance().scrollTop).toEqual(1900);

act(() => {
Expand Down
31 changes: 21 additions & 10 deletions tests/scroll.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,13 @@ describe('List.Scroll', () => {
jest.useFakeTimers();
const listRef = React.createRef();
const wrapper = genList({ itemHeight: 20, height: 100, data: genData(100), ref: listRef });
jest.runAllTimers();

listRef.current.scrollTo(null);
act(() => {
jest.runAllTimers();

listRef.current.scrollTo(null);
});

expect(wrapper.find('.rc-virtual-list-scrollbar-thumb').props().style.display).not.toEqual(
'none',
);
Expand All @@ -107,8 +111,10 @@ describe('List.Scroll', () => {
it('value scroll', () => {
const listRef = React.createRef();
const wrapper = genList({ itemHeight: 20, height: 100, data: genData(100), ref: listRef });
listRef.current.scrollTo(903);
jest.runAllTimers();
act(() => {
listRef.current.scrollTo(903);
jest.runAllTimers();
});
expect(wrapper.find('ul').instance().scrollTop).toEqual(903);

wrapper.unmount();
Expand All @@ -125,9 +131,8 @@ describe('List.Scroll', () => {
...result,
ref,
scrollTo: (...args) => {
ref.current.scrollTo(...args);

act(() => {
ref.current.scrollTo(...args);
jest.runAllTimers();
});
},
Expand All @@ -153,8 +158,10 @@ describe('List.Scroll', () => {

it('scroll top should not out of range', () => {
const { scrollTo, container } = presetList();
scrollTo({ index: 0, align: 'bottom' });
jest.runAllTimers();
act(() => {
scrollTo({ index: 0, align: 'bottom' });
jest.runAllTimers();
});
expect(container.querySelector('ul').scrollTop).toEqual(0);
});

Expand Down Expand Up @@ -389,9 +396,13 @@ describe('List.Scroll', () => {
ref: listRef,
direction: 'rtl',
});
jest.runAllTimers();

listRef.current.scrollTo(null);
act(() => {
jest.runAllTimers();

listRef.current.scrollTo(null);
});

expect(wrapper.find('.rc-virtual-list-scrollbar-thumb').props().style.display).not.toEqual(
'none',
);
Expand Down
8 changes: 6 additions & 2 deletions tests/scrollWidth.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,14 @@ describe('List.scrollWidth', () => {
ref: listRef,
});

listRef.current.scrollTo({ left: 135 });
act(() => {
listRef.current.scrollTo({ left: 135 });
});
expect(listRef.current.getScrollInfo()).toEqual({ x: 135, y: 0 });

listRef.current.scrollTo({ left: -99 });
act(() => {
listRef.current.scrollTo({ left: -99 });
});
expect(listRef.current.getScrollInfo()).toEqual({ x: 0, y: 0 });
});

Expand Down
Loading
Loading