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
12 changes: 6 additions & 6 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,14 @@ export default [{
'react-hooks/error-boundaries': ERROR,
'react-hooks/component-hook-factories': ERROR,
'react-hooks/gating': ERROR,
// 'react-hooks/globals': ERROR,
'react-hooks/globals': ERROR,
// 'react-hooks/immutability': ERROR,
// 'react-hooks/preserve-manual-memoization': ERROR,
// 'react-hooks/purity': ERROR,
// 'react-hooks/refs': ERROR,
// 'react-hooks/set-state-in-effect': ERROR,
// 'react-hooks/preserve-manual-memoization': ERROR, // No idea how to turn this one on yet
'react-hooks/purity': ERROR,
// 'react-hooks/refs': ERROR, // can't turn on until https://github.com/facebook/react/issues/34775 is fixed
'react-hooks/set-state-in-effect': ERROR,
'react-hooks/set-state-in-render': ERROR,
// 'react-hooks/static-components': ERROR,
'react-hooks/static-components': ERROR,
'react-hooks/unsupported-syntax': WARN,
'react-hooks/use-memo': ERROR,
'react-hooks/incompatible-library': WARN,
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-aria/dnd/stories/Reorderable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export function ReorderableGridExample(props: any): JSX.Element {
);
}

let randomDragTypeReorderExample = `keys-${Math.random().toString(36).slice(2)}`;
function ReorderableGrid(props) {
let ref = React.useRef<HTMLDivElement>(null);
let state = useListState(props);
Expand All @@ -91,7 +92,7 @@ function ReorderableGrid(props) {
});

// Use a random drag type so the items can only be reordered within this list and not dragged elsewhere.
let dragType = React.useMemo(() => `keys-${Math.random().toString(36).slice(2)}`, []);
let dragType = React.useMemo(() => randomDragTypeReorderExample, []);
let preview = useRef(null);
let dragState = useDraggableCollectionState({
collection: gridState.collection,
Expand Down
14 changes: 9 additions & 5 deletions packages/@react-aria/dnd/test/dnd.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {CUSTOM_DRAG_TYPE} from '../src/constants';
import {DataTransfer, DataTransferItem, DragEvent, FileSystemDirectoryEntry, FileSystemFileEntry} from './mocks';
import {Draggable, Droppable} from './examples';
import {DragTypes} from '../src/utils';
import React from 'react';
import React, {useEffect} from 'react';
import userEvent from '@testing-library/user-event';

function pointerEvent(type, opts) {
Expand Down Expand Up @@ -195,13 +195,13 @@ describe('useDrag and useDrop', function () {
let draggable = tree.getByText('Drag me');
let droppable = tree.getByText('Drop here');
expect(droppable).toHaveAttribute('data-droptarget', 'false');

let dataTransfer = new DataTransfer();
fireEvent(draggable, new DragEvent('dragstart', {dataTransfer, clientX: 0, clientY: 0}));
act(() => jest.runAllTimers());
expect(draggable).toHaveAttribute('data-dragging', 'true');
expect(droppable).toHaveAttribute('data-droptarget', 'false');

expect(onDragStart).toHaveBeenCalledTimes(1);
expect(onDragMove).not.toHaveBeenCalled();
expect(onDragEnd).not.toHaveBeenCalled();
Expand Down Expand Up @@ -2574,7 +2574,9 @@ describe('useDrag and useDrop', function () {
let setShowTarget2;
let Test = () => {
let [showTarget2, _setShowTarget2] = React.useState(false);
setShowTarget2 = _setShowTarget2;
useEffect(() => {
setShowTarget2 = _setShowTarget2;
}, [_setShowTarget2]);
return (<>
<Draggable />
<Droppable />
Expand Down Expand Up @@ -2635,7 +2637,9 @@ describe('useDrag and useDrop', function () {
let setShowTarget2;
let Test = () => {
let [showTarget2, _setShowTarget2] = React.useState(true);
setShowTarget2 = _setShowTarget2;
useEffect(() => {
setShowTarget2 = _setShowTarget2;
}, [_setShowTarget2]);
return (<>
<Draggable />
<Droppable />
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-aria/menu/src/useSafelyMouseToSubmenu.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import {RefObject} from '@react-types/shared';
import {useEffect, useRef, useState} from 'react';
import {useEffectEvent, useResizeObserver} from '@react-aria/utils';
import {useEffectEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';
import {useInteractionModality} from '@react-aria/interactions';

interface SafelyMouseToSubmenuOptions {
Expand Down Expand Up @@ -67,7 +67,7 @@ export function useSafelyMouseToSubmenu(options: SafelyMouseToSubmenuOptions): v
}
}, [menuRef, preventPointerEvents]);

useEffect(() => {
useLayoutEffect(() => {
let submenu = submenuRef.current;
let menu = menuRef.current;

Expand Down
4 changes: 2 additions & 2 deletions packages/@react-aria/toast/src/useToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import {AriaButtonProps} from '@react-types/button';
import {AriaLabelingProps, DOMAttributes, FocusableElement, RefObject} from '@react-types/shared';
import {filterDOMProps, useId, useSlotId} from '@react-aria/utils';
import {filterDOMProps, useId, useLayoutEffect, useSlotId} from '@react-aria/utils';
// @ts-ignore
import intlMessages from '../intl/*.json';
import {QueuedToast, ToastState} from '@react-stately/toast';
Expand Down Expand Up @@ -68,7 +68,7 @@ export function useToast<T>(props: AriaToastProps<T>, state: ToastState<T>, ref:
// Originally was tied to animationStart/End via https://github.com/adobe/react-spectrum/pull/6223/commits/e22e319df64958e822ab7cd9685e96818cae9ba5
// but toasts don't always have animations.
let [isVisible, setIsVisible] = useState(false);
useEffect(() => {
useLayoutEffect(() => {
setIsVisible(true);
}, []);

Expand Down
23 changes: 16 additions & 7 deletions packages/@react-aria/utils/test/mergeRefs.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/

import {mergeRefs} from '../';
import React, {useCallback, useRef} from 'react';
import React, {useCallback, useEffect, useRef} from 'react';
import {render} from '@react-spectrum/test-utils-internal';

describe('mergeRefs', () => {
Expand All @@ -20,16 +20,21 @@ describe('mergeRefs', () => {
let ref2;

const TextField = (props) => {
ref1 = useRef(null);
ref2 = useRef(null);
let internalRef1 = useRef(null);
let internalRef2 = useRef(null);
useEffect(() => {
ref1 = internalRef1;
ref2 = internalRef2;
}, [internalRef1, internalRef2]);

const ref = mergeRefs(ref1, ref2);
const ref = mergeRefs(internalRef1, internalRef2);
return <input {...props} ref={ref} />;
};

render(<TextField foo="foo" />);

expect(ref1.current).toBe(ref2.current);
expect(ref1.current).not.toBeNull();
});

if (parseInt(React.version.split('.')[0], 10) >= 19) {
Expand All @@ -40,14 +45,18 @@ describe('mergeRefs', () => {
let target = null;

const TextField = (props) => {
ref1 = useRef(null);
ref2 = useRef(null);
let internalRef1 = useRef(null);
let internalRef2 = useRef(null);
useEffect(() => {
ref1 = internalRef1;
ref2 = internalRef2;
}, [internalRef1, internalRef2]);
let ref3 = useCallback((node) => {
target = node;
return cleanUp;
}, []);

const ref = mergeRefs(ref1, ref2, ref3);
const ref = mergeRefs(internalRef1, internalRef2, ref3);
return <input {...props} ref={ref} />;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ function ForwardSearchAutocompleteInput<T>(props: SearchAutocompleteInputProps<T
}
} else if (!isLoading) {
// If loading is no longer happening, clear any timers and hide the loading circle
setShowLoading(false);
if (timeout.current != null) {
clearTimeout(timeout.current);
timeout.current = null;
Expand All @@ -297,6 +296,11 @@ function ForwardSearchAutocompleteInput<T>(props: SearchAutocompleteInputProps<T

lastInputValue.current = inputValue;
}, [isLoading, showLoading, inputValue]);
let [prevIsLoading, setPrevIsLoading] = useState(isLoading);
if (prevIsLoading !== isLoading && !isLoading) {
setShowLoading(false);
setPrevIsLoading(isLoading);
}

return (
(<FocusRing
Expand Down
13 changes: 6 additions & 7 deletions packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {act, pointerMap, render, within} from '@react-spectrum/test-utils-intern
import {Breadcrumbs} from '../';
import {Item} from '@react-stately/collections';
import {Provider} from '@react-spectrum/provider';
import React, {useRef} from 'react';
import React, {createRef, forwardRef} from 'react';
import {theme} from '@react-spectrum/theme-default';
import userEvent from '@testing-library/user-event';

Expand Down Expand Up @@ -93,16 +93,15 @@ describe('Breadcrumbs', function () {
});

it('Should handle forward ref', function () {
let ref;
let Component = () => {
ref = useRef();
let ref = createRef();
let Component = forwardRef((props, forwardedRef) => {
return (
<Breadcrumbs ref={ref} aria-label="breadcrumbs-test">
<Breadcrumbs ref={forwardedRef} aria-label="breadcrumbs-test">
<Item>Folder 1</Item>
</Breadcrumbs>
);
};
let {getByLabelText} = render(<Component />);
});
let {getByLabelText} = render(<Component ref={ref} />);
let breadcrumb = getByLabelText('breadcrumbs-test');
expect(breadcrumb).toBe(ref.current.UNSAFE_getDOMNode());
});
Expand Down
6 changes: 3 additions & 3 deletions packages/@react-spectrum/color/src/ColorWheel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import {classNames, dimensionValue, useFocusableRef, useStyleProps} from '@react
import {ColorThumb} from './ColorThumb';
import {ColorWheelContext, useContextProps} from 'react-aria-components';
import {FocusableRef} from '@react-types/shared';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import React, {useCallback, useRef, useState} from 'react';
import {SpectrumColorWheelProps} from '@react-types/color';
import styles from '@adobe/spectrum-css-temp/components/colorwheel/vars.css';
import {useColorWheel} from '@react-aria/color';
import {useColorWheelState} from '@react-stately/color';
import {useFocusRing} from '@react-aria/focus';
import {useLayoutEffect, useResizeObserver} from '@react-aria/utils';
import {useProviderProps} from '@react-spectrum/provider';
import {useResizeObserver} from '@react-aria/utils';

const WHEEL_THICKNESS = 24;

Expand Down Expand Up @@ -53,7 +53,7 @@ export const ColorWheel = React.forwardRef(function ColorWheel(props: SpectrumCo
}
}, [containerRef, setWheelRadius, setWheelThickness]);

useEffect(() => {
useLayoutEffect(() => {
// the size observer's fallback to the window resize event doesn't fire on mount
if (wheelRadius === 0) {
resizeHandler();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ export const Default: ColorSwatchPickerStory = (args) => (
</ColorSwatchPicker>
);

let randomColors = Array.from(Array(24)).map(() => {
return `#${Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0')}`;
});
export const ManySwatches: ColorSwatchPickerStory = (args) => (
<ColorSwatchPicker {...args} maxWidth="size-3000">
{Array.from(Array(24)).map(() => {
let color = `#${Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0')}`;
{randomColors.map((color) => {
return <ColorSwatch key={color} color={color} />;
})}
</ColorSwatchPicker>
Expand Down
8 changes: 6 additions & 2 deletions packages/@react-spectrum/combobox/src/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,6 @@ const ComboBoxInput = React.forwardRef(function ComboBoxInput(props: ComboBoxInp
}, 500);
}
} else if (!isLoading) {
// If loading is no longer happening, clear any timers and hide the loading circle
setShowLoading(false);
if (timeout.current) {
clearTimeout(timeout.current);
}
Expand All @@ -289,6 +287,12 @@ const ComboBoxInput = React.forwardRef(function ComboBoxInput(props: ComboBoxInp
lastInputValue.current = inputValue;
}, [isLoading, showLoading, inputValue]);

let [prevIsLoading, setPrevIsLoading] = useState(isLoading);
if (prevIsLoading !== isLoading && !isLoading) {
setShowLoading(false);
setPrevIsLoading(isLoading);
}

useEffect(() => {
return () => {
if (timeout.current) {
Expand Down
10 changes: 7 additions & 3 deletions packages/@react-spectrum/list/stories/ListViewDnDExamples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,15 @@ let itemList2 = [
{id: '12', type: 'item', textValue: 'Item Twelve'}
];

let randomDragTypeReorderExample = `keys-${Math.random().toString(36).slice(2)}`;
export function ReorderExample(props: SpectrumListViewProps<any> & DragAndDropOptions & {getAllowedDropOperationsAction?: () => void}): JSX.Element {
let {items, onDrop, onDragStart, onDragEnd, disabledKeys = ['2'], ...otherprops} = props;
let list = useListData({
initialItems: items ? [...items] : itemList1
});

// Use a random drag type so the items can only be reordered within this list and not dragged elsewhere.
let dragType = React.useMemo(() => `keys-${Math.random().toString(36).slice(2)}`, []);
let dragType = React.useMemo(() => randomDragTypeReorderExample, []);

let onMove = (keys: Key[], target: ItemDropTarget) => {
if (target.dropPosition === 'before') {
Expand Down Expand Up @@ -166,6 +167,7 @@ export function ReorderExample(props: SpectrumListViewProps<any> & DragAndDropOp
);
}

let randomDragTypeDragIntoItemExample = `keys-${Math.random().toString(36).slice(2)}`;
export function DragIntoItemExample(props: {listViewProps: SpectrumListViewProps<any>, dragHookOptions?: DragAndDropOptions, dropHookOptions?: DragAndDropOptions, getAllowedDropOperationsAction?: () => void}): JSX.Element {
let {
listViewProps = {},
Expand Down Expand Up @@ -193,7 +195,7 @@ export function DragIntoItemExample(props: {listViewProps: SpectrumListViewProps
let disabledKeys: Key[] = ['2', '7'];

// Use a random drag type so the items can only be reordered within this list and not dragged elsewhere.
let dragType = React.useMemo(() => `keys-${Math.random().toString(36).slice(2)}`, []);
let dragType = React.useMemo(() => randomDragTypeDragIntoItemExample, []);

let onMove = (keys: Key[], target: ItemDropTarget) => {
let folderItem = list.getItem(target.key)!;
Expand Down Expand Up @@ -274,6 +276,8 @@ export function DragIntoItemExample(props: {listViewProps: SpectrumListViewProps
);
}

let randomDragTypeDragBetweenListsExample = `keys-${Math.random().toString(36).slice(2)}`;

export function DragBetweenListsExample(props: SpectrumListViewProps<any> & DragAndDropOptions & {getAllowedDropOperationsAction?: () => void, items1?: any[], items2?: any[]}): JSX.Element {
let {onDragStart, onDragEnd, onDrop} = props;
let onDropAction = chain(action('onDrop'), onDrop);
Expand Down Expand Up @@ -311,7 +315,7 @@ export function DragBetweenListsExample(props: SpectrumListViewProps<any> & Drag
};

// Use a random drag type so the items can only be reordered within the two lists and not dragged elsewhere.
let dragType = React.useMemo(() => `keys-${Math.random().toString(36).slice(2)}`, []);
let dragType = React.useMemo(() => randomDragTypeDragBetweenListsExample, []);

let {dragAndDropHooks} = useDragAndDrop({
getItems(keys) {
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-spectrum/menu/src/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ export const Menu = React.forwardRef(function Menu<T extends object>(props: Spec
useSyncRef(contextProps, domRef);
let [leftOffset, setLeftOffset] = useState({left: 0});
let prevPopoverContainer = useRef<HTMLElement | null>(null);
useEffect(() => {

useLayoutEffect(() => {
if (popoverContainer && prevPopoverContainer.current !== popoverContainer && leftOffset.left === 0) {
prevPopoverContainer.current = popoverContainer;
let {left} = popoverContainer.getBoundingClientRect();
Expand Down
Loading
Loading