From 6b063ff4f4d8bfc33807ed5ec0bd526a0b67b4d0 Mon Sep 17 00:00:00 2001 From: xienan <1633875789@qq.com> Date: Sat, 22 Nov 2025 23:40:35 +0800 Subject: [PATCH 1/2] fix: use scrollIntoParentView to prevent page scroll When Cascader has a defaultValue, opening it for the first time causes the page to scroll to the top due to native scrollIntoView behavior. This change replaces it with scrollIntoParentView to ensure scrolling is confined to the dropdown container. --- src/OptionList/Column.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/OptionList/Column.tsx b/src/OptionList/Column.tsx index db7f0b16..fbc0c38e 100644 --- a/src/OptionList/Column.tsx +++ b/src/OptionList/Column.tsx @@ -4,7 +4,7 @@ import pickAttrs from '@rc-component/util/lib/pickAttrs'; import type { DefaultOptionType, SingleValueType } from '../Cascader'; import CascaderContext from '../context'; import { SEARCH_MARK } from '../hooks/useSearchOptions'; -import { isLeaf, toPathKey } from '../utils/commonUtil'; +import { isLeaf, scrollIntoParentView, toPathKey } from '../utils/commonUtil'; import Checkbox from './Checkbox'; export const FIX_LABEL = '__cascader_fix_label__'; @@ -110,10 +110,7 @@ export default function Column(selector); if (activeElement) { - activeElement.scrollIntoView({ - block: 'nearest', - inline: 'nearest', - }); + scrollIntoParentView(activeElement); } } }, [activeValue, menuItemPrefixCls]); From c58a0907474cb33b29dd215d6f9314ad8cc1e2ef Mon Sep 17 00:00:00 2001 From: xienan <1633875789@qq.com> Date: Mon, 24 Nov 2025 16:03:19 +0800 Subject: [PATCH 2/2] fix: align scroll behavior and tests to prevent page scroll and jsdom errors --- src/utils/commonUtil.ts | 4 +++- tests/index.spec.tsx | 18 ++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/utils/commonUtil.ts b/src/utils/commonUtil.ts index 7f8c05a5..2f45a49e 100644 --- a/src/utils/commonUtil.ts +++ b/src/utils/commonUtil.ts @@ -53,7 +53,9 @@ export function scrollIntoParentView(element: HTMLElement) { const elementToParent = element.offsetTop - parent.offsetTop; // offsetParent may not be parent. if (elementToParent - parent.scrollTop < 0) { parent.scrollTo({ top: elementToParent }); - } else if (elementToParent + element.offsetHeight - parent.scrollTop > parent.offsetHeight) { + } else if ( + elementToParent + element.offsetHeight - parent.scrollTop > parent.offsetHeight + ) { parent.scrollTo({ top: elementToParent + element.offsetHeight - parent.offsetHeight }); } } diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index a59d0f37..14d47ab4 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -4,7 +4,7 @@ import type { CascaderRef, BaseOptionType, CascaderProps } from '../src'; import Cascader from '../src'; import { addressOptions, addressOptionsForUneven, optionsForActiveMenuItems } from './demoOptions'; import { mount } from './enzyme'; -import { toRawValues } from '../src/utils/commonUtil'; +import * as commonUtil from '../src/utils/commonUtil'; import { act, fireEvent, render } from '@testing-library/react'; import KeyCode from '@rc-component/util/lib/KeyCode'; import { expectOpen, selectOption } from './util'; @@ -1075,7 +1075,7 @@ describe('Cascader.Basic', () => { }); const items = wrapper.container.querySelectorAll('.rc-cascader-menu-item'); fireEvent.mouseEnter(items[9]); - expect(mockScrollTo).toHaveBeenCalledTimes(0); + expect(mockScrollTo).toHaveBeenCalledTimes(1); spyElement.mockRestore(); }); @@ -1094,18 +1094,12 @@ describe('Cascader.Basic', () => { const input = container.querySelector('input')!; fireEvent.focus(input); + const spy = jest.spyOn(commonUtil, 'scrollIntoParentView'); fireEvent.keyDown(input, { key: 'ArrowDown', keyCode: KeyCode.DOWN }); const targetElement = container.querySelector('.rc-cascader-menu-item-active')!; - - const scrollSpy = jest.spyOn(targetElement, 'scrollIntoView').mockImplementation(() => null); - - expect(scrollSpy).toHaveBeenCalledWith({ - block: 'nearest', - inline: 'nearest', - }); - - scrollSpy.mockReset(); + expect(spy).toHaveBeenCalledWith(targetElement); + spy.mockRestore(); }); }); @@ -1149,7 +1143,7 @@ describe('Cascader.Basic', () => { errorSpy.mockReset(); }); it('toRawValues undefined', () => { - expect(toRawValues()).toEqual([]); + expect(commonUtil.toRawValues()).toEqual([]); }); it('nativeElement', () => {