Skip to content
Merged
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"@babel/runtime": "^7.10.1",
"classnames": "^2.2.5",
"rc-resize-observer": "^1.0.0",
"rc-util": "^5.13.0",
"rc-util": "^5.14.0",
"shallowequal": "^1.1.0"
},
"devDependencies": {
Expand Down
21 changes: 12 additions & 9 deletions src/Cell/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
CellEllipsisType,
} from '../interface';
import { getPathValue, validateValue } from '../utils/valueUtil';
import StickyContext from '../context/StickyContext';

function isRenderCell<RecordType>(
data: React.ReactNode | RenderedCell<RecordType>,
Expand Down Expand Up @@ -93,6 +94,8 @@ function Cell<RecordType extends DefaultRecordType>(
): React.ReactElement {
const cellPrefixCls = `${prefixCls}-cell`;

const supportSticky = React.useContext(StickyContext);

// ==================== Child Node ====================
let cellProps: CellType<RecordType>;
let childNode: React.ReactNode;
Expand Down Expand Up @@ -145,8 +148,8 @@ function Cell<RecordType extends DefaultRecordType>(

// ====================== Fixed =======================
const fixedStyle: React.CSSProperties = {};
const isFixLeft = typeof fixLeft === 'number';
const isFixRight = typeof fixRight === 'number';
const isFixLeft = typeof fixLeft === 'number' && supportSticky;
const isFixRight = typeof fixRight === 'number' && supportSticky;

if (isFixLeft) {
fixedStyle.position = 'sticky';
Expand Down Expand Up @@ -185,15 +188,15 @@ function Cell<RecordType extends DefaultRecordType>(
cellPrefixCls,
className,
{
[`${cellPrefixCls}-fix-left`]: isFixLeft,
[`${cellPrefixCls}-fix-left-first`]: firstFixLeft,
[`${cellPrefixCls}-fix-left-last`]: lastFixLeft,
[`${cellPrefixCls}-fix-right`]: isFixRight,
[`${cellPrefixCls}-fix-right-first`]: firstFixRight,
[`${cellPrefixCls}-fix-right-last`]: lastFixRight,
[`${cellPrefixCls}-fix-left`]: isFixLeft && supportSticky,
[`${cellPrefixCls}-fix-left-first`]: firstFixLeft && supportSticky,
[`${cellPrefixCls}-fix-left-last`]: lastFixLeft && supportSticky,
[`${cellPrefixCls}-fix-right`]: isFixRight && supportSticky,
[`${cellPrefixCls}-fix-right-first`]: firstFixRight && supportSticky,
[`${cellPrefixCls}-fix-right-last`]: lastFixRight && supportSticky,
[`${cellPrefixCls}-ellipsis`]: ellipsis,
[`${cellPrefixCls}-with-append`]: appendNode,
[`${cellPrefixCls}-fix-sticky`]: (isFixLeft || isFixRight) && isSticky,
[`${cellPrefixCls}-fix-sticky`]: (isFixLeft || isFixRight) && isSticky && supportSticky,
},
additionalProps.className,
cellClassName,
Expand Down
16 changes: 11 additions & 5 deletions src/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import * as React from 'react';
import isVisible from 'rc-util/lib/Dom/isVisible';
import { isStyleSupport } from 'rc-util/lib/Dom/styleChecker';
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
import warning from 'rc-util/lib/warning';
Expand Down Expand Up @@ -73,6 +74,7 @@ import useSticky from './hooks/useSticky';
import FixedHolder from './FixedHolder';
import type { SummaryProps } from './Footer/Summary';
import Summary from './Footer/Summary';
import StickyContext from './context/StickyContext';

// Used for conditions cache
const EMPTY_DATA = [];
Expand Down Expand Up @@ -502,9 +504,11 @@ function Table<RecordType extends DefaultRecordType>(props: TableProps<RecordTyp

// ===================== Effects ======================
const [scrollbarSize, setScrollbarSize] = React.useState(0);
const [supportSticky, setSupportSticky] = React.useState(true); // Only IE not support, we mark as support first

React.useEffect(() => {
setScrollbarSize(getTargetScrollBarSize(scrollBodyRef.current).width);
setSupportSticky(isStyleSupport('position', 'sticky'));
}, []);

// ================== INTERNAL HOOKS ==================
Expand Down Expand Up @@ -823,11 +827,13 @@ function Table<RecordType extends DefaultRecordType>(props: TableProps<RecordTyp
const ResizeContextValue = React.useMemo(() => ({ onColumnResize }), [onColumnResize]);

return (
<TableContext.Provider value={TableContextValue}>
<BodyContext.Provider value={BodyContextValue}>
<ResizeContext.Provider value={ResizeContextValue}>{fullTable}</ResizeContext.Provider>
</BodyContext.Provider>
</TableContext.Provider>
<StickyContext.Provider value={supportSticky}>
<TableContext.Provider value={TableContextValue}>
<BodyContext.Provider value={BodyContextValue}>
<ResizeContext.Provider value={ResizeContextValue}>{fullTable}</ResizeContext.Provider>
</BodyContext.Provider>
</TableContext.Provider>
</StickyContext.Provider>
);
}

Expand Down
6 changes: 6 additions & 0 deletions src/context/StickyContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as React from 'react';

// Tell cell that browser support sticky
const StickyContext = React.createContext<boolean>(false);

export default StickyContext;
4 changes: 2 additions & 2 deletions src/context/TableContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { GetComponent } from '../interface';
import { FixedInfo } from '../utils/fixUtil';
import type { GetComponent } from '../interface';
import type { FixedInfo } from '../utils/fixUtil';

export interface TableContextProps {
// Table context
Expand Down
7 changes: 4 additions & 3 deletions tests/Cell.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Table from '../src';

describe('Table.Cell', () => {
it('shouldCellUpdate', () => {
let renderTime = 0;
let reRenderTime = 0;

const Demo = () => {
const [, forceUpdate] = React.useState({});
Expand All @@ -18,7 +18,7 @@ describe('Table.Cell', () => {
shouldCellUpdate: (record, prevRecord) => prevRecord.key !== record.key,
dataIndex: 'key',
render: value => {
renderTime += 1;
reRenderTime += 1;
return value;
},
},
Expand All @@ -35,10 +35,11 @@ describe('Table.Cell', () => {
};

const wrapper = mount(<Demo />);
reRenderTime = 0;

for (let i = 0; i < 100; i += 1) {
wrapper.find('button').simulate('click');
expect(renderTime).toEqual(1);
expect(reRenderTime).toEqual(0);
}
});
});
61 changes: 61 additions & 0 deletions tests/FixedColumn-IE.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { isStyleSupport } from 'rc-util/lib/Dom/styleChecker';
import Table from '../src';

jest.mock('rc-util/lib/Dom/styleChecker', () => {
return {
isStyleSupport: (name, val) => val !== 'sticky',
};
});

describe('Table.FixedColumn', () => {
let domSpy;

beforeAll(() => {
domSpy = spyElementPrototype(HTMLElement, 'offsetParent', {
get: () => ({}),
});
});

afterAll(() => {
domSpy.mockRestore();
});

const columns = [
{ title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' },
{ title: 'title2', dataIndex: 'b', key: 'b', width: 100, fixed: 'left' },
{ title: 'title3', dataIndex: 'c', key: 'c' },
{ title: 'title4', dataIndex: 'b', key: 'd' },
{ title: 'title5', dataIndex: 'b', key: 'e' },
{ title: 'title6', dataIndex: 'b', key: 'f' },
{ title: 'title7', dataIndex: 'b', key: 'g' },
{ title: 'title8', dataIndex: 'b', key: 'h' },
{ title: 'title9', dataIndex: 'b', key: 'i' },
{ title: 'title10', dataIndex: 'b', key: 'j' },
{ title: 'title11', dataIndex: 'b', key: 'k' },
{ title: 'title12', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' },
];
const data = [{ a: '123', b: 'xxxxxxxx', d: 3, key: '1' }];

it('not sticky', async () => {
jest.useFakeTimers();
const wrapper = mount(<Table columns={columns} data={data} scroll={{ x: 1200 }} />);

act(() => {
wrapper.find('table ResizeObserver').first().props().onResize({ width: 93, offsetWidth: 93 });
});

await act(async () => {
jest.runAllTimers();
await Promise.resolve();
wrapper.update();
});

expect(wrapper.exists('.rc-table-cell-fix-left')).toBeFalsy();
expect(wrapper.exists('.rc-table-cell-fix-right')).toBeFalsy();
});
});