Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/seo display all invisibly #40

Closed
Closed
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
60 changes: 40 additions & 20 deletions src/Overflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ export interface OverflowProps<ItemType> extends React.HTMLAttributes<any> {

/** @private This API may be refactor since not well design */
onVisibleChange?: (visibleCount: number) => void;

/** When set to `full`, ssr will render full items by default and remove at client side */
ssr?: 'full';
Copy link
Member

Choose a reason for hiding this comment

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

这个不该删的,只是处理 full 的时候做坍缩。不是 full 的时候仍然是不渲染。overflow 不仅仅是 menu 在用。还有其他的响应时需求逻辑是不一样的。

Copy link
Author

Choose a reason for hiding this comment

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

猴猴,我缩小了改动的区域,在 full 且需要responsive的时候才做坍缩。麻烦 review 这条哦:#41

}

function defaultRenderRest<ItemType>(omittedItems: ItemType[]) {
Expand All @@ -59,7 +56,6 @@ function Overflow<ItemType = any>(
renderRawItem,
itemKey,
itemWidth = 10,
ssr,
style,
className,
maxCount,
Expand All @@ -72,8 +68,6 @@ function Overflow<ItemType = any>(
...restProps
} = props;

const fullySSR = ssr === 'full';

const notifyEffectUpdate = useBatcher();

const [containerWidth, setContainerWidth] = useEffectState<number>(
Expand Down Expand Up @@ -104,7 +98,7 @@ function Overflow<ItemType = any>(

const [displayCount, setDisplayCount] = useState<number>(null);
const mergedDisplayCount = React.useMemo(() => {
if (displayCount === null && fullySSR) {
if (displayCount === null) {
return Number.MAX_SAFE_INTEGER;
}

Expand Down Expand Up @@ -134,9 +128,7 @@ function Overflow<ItemType = any>(
let items = data;

if (shouldResponsive) {
if (containerWidth === null && fullySSR) {
items = data;
} else {
if (containerWidth !== null) {
items = data.slice(
0,
Math.min(data.length, mergedContainerWidth / itemWidth),
Expand All @@ -147,7 +139,14 @@ function Overflow<ItemType = any>(
}

return items;
}, [data, itemWidth, containerWidth, maxCount, shouldResponsive]);
}, [
data,
itemWidth,
containerWidth,
maxCount,
shouldResponsive,
mergedContainerWidth,
]);

const omittedItems = useMemo(() => {
if (shouldResponsive) {
Expand Down Expand Up @@ -250,12 +249,7 @@ function Overflow<ItemType = any>(
}

for (let i = 0; i < len; i += 1) {
let currentItemWidth = getItemWidth(i);

// Fully will always render
if (fullySSR) {
currentItemWidth = currentItemWidth || 0;
}
const currentItemWidth = getItemWidth(i);

// Break since data not ready
if (currentItemWidth === undefined) {
Expand Down Expand Up @@ -301,8 +295,18 @@ function Overflow<ItemType = any>(

// ================================ Render ================================
const displayRest = restReady && !!omittedItems.length;
const isResponsiveAndFirstRender = isResponsive && containerWidth === null;
const responsiveAndFirstRenderStyle: React.CSSProperties = {
maxWidth: 0,
padding: 0,
margin: 0,
borderWidth: 0,
overflowX: 'hidden',
};

let suffixStyle: React.CSSProperties = {};
let suffixStyle: React.CSSProperties = isResponsiveAndFirstRender
? responsiveAndFirstRenderStyle
: {};
if (suffixFixedStart !== null && shouldResponsive) {
suffixStyle = {
position: 'absolute',
Expand All @@ -316,12 +320,22 @@ function Overflow<ItemType = any>(
responsive: shouldResponsive,
component: itemComponent,
invalidate,
style: isResponsiveAndFirstRender
? responsiveAndFirstRenderStyle
: undefined,
};

// >>>>> Choice render fun by `renderRawItem`
const internalRenderItemNode = renderRawItem
? (item: ItemType, index: number) => {
const key = getKey(item, index);
const isIdxCheckPass = index <= mergedDisplayCount;
// in responsive case, item's `display` can be set to `true` when:
// 1) at initial render; 2) its corresponding width is valid and pass the index check
const shouldDisplay = isResponsive
? isResponsiveAndFirstRender ||
(isIdxCheckPass && getItemWidth(index) > 0)
: isIdxCheckPass;

return (
<OverflowContext.Provider
Expand All @@ -332,7 +346,7 @@ function Overflow<ItemType = any>(
item,
itemKey: key,
registerSize,
display: index <= mergedDisplayCount,
display: shouldDisplay,
}}
>
{renderRawItem(item, index)}
Expand All @@ -341,6 +355,12 @@ function Overflow<ItemType = any>(
}
: (item: ItemType, index: number) => {
const key = getKey(item, index);
const isIdxCheckPass = index <= mergedDisplayCount;

const shouldDisplay = isResponsive
? isResponsiveAndFirstRender ||
(isIdxCheckPass && getItemWidth(index) > 0)
: isIdxCheckPass;

return (
<Item
Expand All @@ -351,7 +371,7 @@ function Overflow<ItemType = any>(
renderItem={mergedRenderItem}
itemKey={key}
registerSize={registerSize}
display={index <= mergedDisplayCount}
display={shouldDisplay}
/>
);
};
Expand Down
140 changes: 140 additions & 0 deletions tests/__snapshots__/seo.spec.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Overflow.SEO invalidate number with suffix 1`] = `
<div
class=""
>
<div
class=""
>
Label 0
</div>
<div
class=""
>
Label 1
</div>
<div
class=""
>
Label 2
</div>
<div
class=""
>
Label 3
</div>
<div
class="rc-overflow-item-suffix"
>
<span>
I am a suffix
</span>
</div>
</div>
`;

exports[`Overflow.SEO maxCount number with suffix 1`] = `
<div
class="rc-overflow"
>
<div
class="rc-overflow-item"
style="opacity:1"
>
Label 0
</div>
<div
class="rc-overflow-item"
style="opacity:1"
>
Label 1
</div>
<div
class="rc-overflow-item"
style="opacity:1"
>
Label 2
</div>
<div
class="rc-overflow-item"
style="opacity:1"
>
Label 3
</div>
<div
class="rc-overflow-item rc-overflow-item-rest"
style="opacity:1"
>
+ 2 ...
</div>
<div
class="rc-overflow-item rc-overflow-item-suffix"
style="opacity:1"
>
<span>
I am a suffix
</span>
</div>
</div>
`;

exports[`Overflow.SEO responsive 1`] = `
<div
class="rc-overflow"
>
<div
class="rc-overflow-item"
style="opacity:1;order:0;max-width:0;padding:0;margin:0;border-width:0;overflow-x:hidden"
>
Label 0
</div>
<div
class="rc-overflow-item"
style="opacity:1;order:1;max-width:0;padding:0;margin:0;border-width:0;overflow-x:hidden"
>
Label 1
</div>
<div
aria-hidden="true"
class="rc-overflow-item rc-overflow-item-rest"
style="opacity:0;height:0;overflow-y:hidden;order:9007199254740991;pointer-events:none;position:absolute;max-width:0;padding:0;margin:0;border-width:0;overflow-x:hidden"
>
+ 0 ...
</div>
</div>
`;

exports[`Overflow.SEO responsive with suffix 1`] = `
<div
class="rc-overflow"
>
<div
class="rc-overflow-item"
style="opacity:1;order:0;max-width:0;padding:0;margin:0;border-width:0;overflow-x:hidden"
>
Label 0
</div>
<div
class="rc-overflow-item"
style="opacity:1;order:1;max-width:0;padding:0;margin:0;border-width:0;overflow-x:hidden"
>
Label 1
</div>
<div
aria-hidden="true"
class="rc-overflow-item rc-overflow-item-rest"
style="opacity:0;height:0;overflow-y:hidden;order:9007199254740991;pointer-events:none;position:absolute;max-width:0;padding:0;margin:0;border-width:0;overflow-x:hidden"
>
+ 0 ...
</div>
<div
class="rc-overflow-item rc-overflow-item-suffix"
style="opacity:1;order:9007199254740991;max-width:0;padding:0;margin:0;border-width:0;overflow-x:hidden"
>
<span>
I am a suffix
</span>
</div>
</div>
`;
27 changes: 0 additions & 27 deletions tests/__snapshots__/ssr.spec.tsx.snap

This file was deleted.

78 changes: 78 additions & 0 deletions tests/seo.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react';
import { render } from 'enzyme';
import Overflow from '../src';
import type { OverflowProps } from '../src';

interface ItemType {
label: React.ReactNode;
key: React.Key;
}

interface CaseConf {
name: string;
dataLength: number;
maxCount: OverflowProps<ItemType>['maxCount'];
suffix?: boolean;
}

function renderItem(item: ItemType) {
return item.label;
}

describe('Overflow.SEO', () => {
function getData(count: number) {
return new Array(count).fill(undefined).map((_, index) => ({
label: `Label ${index}`,
key: `k-${index}`,
}));
}

beforeEach(() => {
jest.useFakeTimers();
});

afterEach(() => {
jest.useRealTimers();
});

const testCases: CaseConf[] = [
{
name: 'responsive',
dataLength: 2,
maxCount: 'responsive',
},
{
name: 'responsive with suffix',
dataLength: 2,
maxCount: 'responsive',
suffix: true,
},
{
name: 'maxCount number with suffix',
dataLength: 6,
maxCount: 4,
suffix: true,
},
{
name: 'invalidate number with suffix',
dataLength: 4,
maxCount: 'invalidate',
suffix: true,
},
];

testCases.forEach(({ name, dataLength, maxCount: maxCountVal, suffix }) => {
it(`${name}`, () => {
const wrapper = render(
<Overflow<ItemType>
data={getData(dataLength)}
renderItem={renderItem}
maxCount={maxCountVal}
suffix={suffix && <span> I am a suffix </span>}
/>,
);

expect(wrapper).toMatchSnapshot();
});
});
});
Loading
Loading