Skip to content

Commit

Permalink
fix: Delay collection which makes scroll not working (#650)
Browse files Browse the repository at this point in the history
* chore: useUpdate for in frame

* fix: limitation check

* chore: clean up

* chore: not care scroll

* chore: add additional check

* fix: ping logic
  • Loading branch information
zombieJ authored Feb 21, 2023
1 parent 20b2f41 commit 89d01ff
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 68 deletions.
2 changes: 1 addition & 1 deletion docs/examples/editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Tabs from '../../src';
import '../../assets/index.less';

export default () => {
const countRef = useRef(10);
const countRef = useRef(8);
const [tabs, setTabs] = React.useState(
new Array(countRef.current).fill(0).map((_, index) => {
return {
Expand Down
28 changes: 18 additions & 10 deletions src/TabNavList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
import useEvent from 'rc-util/lib/hooks/useEvent';
import raf from 'rc-util/lib/raf';
import { useComposeRef } from 'rc-util/lib/ref';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
import useOffsets from '../hooks/useOffsets';
import useRaf, { useRafState } from '../hooks/useRaf';
import useSyncState from '../hooks/useSyncState';
import useTouchMove from '../hooks/useTouchMove';
import useUpdate, { useUpdateState } from '../hooks/useUpdate';
import useVisibleRange from '../hooks/useVisibleRange';
import type {
AnimatedConfig,
Expand Down Expand Up @@ -107,7 +108,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
const [addSize, setAddSize] = useState<SizeInfo>([0, 0]);
const [operationSize, setOperationSize] = useState<SizeInfo>([0, 0]);

const [tabSizes, setTabSizes] = useRafState<TabSizeMap>(new Map());
const [tabSizes, setTabSizes] = useUpdateState<TabSizeMap>(new Map());
const tabOffsets = useOffsets(tabs, tabSizes, tabContentSize[0]);

// ========================== Unit =========================
Expand Down Expand Up @@ -173,7 +174,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
}

// Skip scroll if place is enough
if (containerExcludeExtraSizeValue >= tabContentSizeValue) {
if (!needScroll) {
return false;
}

Expand Down Expand Up @@ -218,7 +219,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
);

// ========================= Scroll ========================
const scrollToTab = (key = activeKey) => {
const scrollToTab = useEvent((key = activeKey) => {
const tabOffset = tabOffsets.get(key) || {
width: 0,
height: 0,
Expand Down Expand Up @@ -261,7 +262,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
setTransformLeft(0);
setTransformTop(alignInRange(newTransform));
}
};
});

// ========================== Tab ==========================
const tabNodeStyle: React.CSSProperties = {};
Expand Down Expand Up @@ -327,7 +328,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
updateTabSizes();
}, [tabs.map(tab => tab.key).join('_')]);

const onListHolderResize = useRaf(() => {
const onListHolderResize = useUpdate(() => {
// Update wrapper records
const containerSize = getSize(containerRef);
const extraLeftSize = getSize(extraLeftRef);
Expand Down Expand Up @@ -400,7 +401,14 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
useEffect(() => {
scrollToTab();
// eslint-disable-next-line
}, [activeKey, stringify(activeTabOffset), stringify(tabOffsets), tabPositionTopOrBottom]);
}, [
activeKey,
transformMin,
transformMax,
stringify(activeTabOffset),
stringify(tabOffsets),
tabPositionTopOrBottom,
]);

// Should recalculate when rtl changed
useEffect(() => {
Expand All @@ -419,14 +427,14 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
if (tabPositionTopOrBottom) {
if (rtl) {
pingRight = transformLeft > 0;
pingLeft = transformLeft + containerExcludeExtraSizeValue < tabContentSizeValue;
pingLeft = transformLeft !== transformMax;
} else {
pingLeft = transformLeft < 0;
pingRight = -transformLeft + containerExcludeExtraSizeValue < tabContentSizeValue;
pingRight = transformLeft !== transformMin;
}
} else {
pingTop = transformTop < 0;
pingBottom = -transformTop + containerExcludeExtraSizeValue < tabContentSizeValue;
pingBottom = transformTop !== transformMin;
}

return (
Expand Down
56 changes: 0 additions & 56 deletions src/hooks/useRaf.ts

This file was deleted.

58 changes: 58 additions & 0 deletions src/hooks/useUpdate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useLayoutUpdateEffect } from 'rc-util/lib/hooks/useLayoutEffect';
import { useRef, useState } from 'react';

/**
* Help to merge callback with `useLayoutEffect`.
* One time will only trigger once.
*/
export default function useUpdate(callback: VoidFunction): () => void {
const [count, setCount] = useState(0);
const effectRef = useRef(0);
const callbackRef = useRef<VoidFunction>();
callbackRef.current = callback;

// Trigger on `useLayoutEffect`
useLayoutUpdateEffect(() => {
callbackRef.current?.();
}, [count]);

// Trigger to update count
return () => {
if (effectRef.current !== count) {
return;
}

effectRef.current += 1;
setCount(effectRef.current);
};
}

type Callback<T> = (ori: T) => T;

export function useUpdateState<T>(
defaultState: T | (() => T),
): [T, (updater: Callback<T>) => void] {
const batchRef = useRef<Callback<T>[]>([]);
const [, forceUpdate] = useState({});
const state = useRef<T>(
typeof defaultState === 'function' ? (defaultState as any)() : defaultState,
);

const flushUpdate = useUpdate(() => {
let current = state.current;
batchRef.current.forEach(callback => {
current = callback(current);
});
batchRef.current = [];

state.current = current;
forceUpdate({});
});

function updater(callback: Callback<T>) {
batchRef.current.push(callback);
flushUpdate();
}

return [state.current, updater];
}
2 changes: 1 addition & 1 deletion tests/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ exports[`Tabs.Basic Normal 1`] = `
role="tablist"
>
<div
class="rc-tabs-nav-wrap"
class="rc-tabs-nav-wrap rc-tabs-nav-wrap-ping-right"
>
<div
class="rc-tabs-nav-list"
Expand Down

1 comment on commit 89d01ff

@vercel
Copy link

@vercel vercel bot commented on 89d01ff Feb 21, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

tabs – ./

tabs-react-component.vercel.app
tabs-git-master-react-component.vercel.app

Please sign in to comment.