Skip to content

Commit 3262064

Browse files
authored
fix: Invalid items animation on screen change (#396)
## Description Describe what was changed in this pull request ## Changes showcase Include example images/recordings if the new feature introduces some visual changes or the PR fixes a UI bug
1 parent 273491c commit 3262064

File tree

13 files changed

+51
-247
lines changed

13 files changed

+51
-247
lines changed

packages/react-native-sortables/src/components/SortableFlex.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ function SortableFlex(props: SortableFlexProps) {
2727
...styleProps
2828
},
2929
sharedProps: {
30+
debug,
3031
dimensionsAnimationType,
3132
DropIndicatorComponent,
3233
dropIndicatorStyle,
3334
itemEntering,
3435
itemExiting,
35-
itemsLayout,
3636
overflow,
3737
reorderTriggerOrigin,
3838
showDropIndicator,
@@ -64,6 +64,7 @@ function SortableFlex(props: SortableFlexProps) {
6464
<SharedProvider
6565
{...sharedProps}
6666
controlledContainerDimensions={controlledContainerDimensions}
67+
debug={debug}
6768
initialItemsStyleOverride={styles.styleOverride}
6869
itemKeys={itemKeys}
6970
onDragEnd={onDragEnd}>
@@ -77,12 +78,12 @@ function SortableFlex(props: SortableFlexProps) {
7778
/>
7879
<SortableFlexInner
7980
childrenArray={childrenArray}
81+
debug={debug}
8082
dimensionsAnimationType={dimensionsAnimationType}
8183
DropIndicatorComponent={DropIndicatorComponent}
8284
dropIndicatorStyle={dropIndicatorStyle}
8385
itemEntering={itemEntering}
8486
itemExiting={itemExiting}
85-
itemsLayout={itemsLayout}
8687
overflow={overflow}
8788
showDropIndicator={showDropIndicator}
8889
style={[
@@ -102,10 +103,10 @@ type SortableFlexInnerProps = DropIndicatorSettings &
102103
Required<
103104
Pick<
104105
SortableFlexProps,
106+
| 'debug'
105107
| 'dimensionsAnimationType'
106108
| 'itemEntering'
107109
| 'itemExiting'
108-
| 'itemsLayout'
109110
| 'overflow'
110111
>
111112
> & {
@@ -117,7 +118,6 @@ function SortableFlexInner({
117118
childrenArray,
118119
itemEntering,
119120
itemExiting,
120-
itemsLayout,
121121
style,
122122
...containerProps
123123
}: SortableFlexInnerProps) {
@@ -128,8 +128,7 @@ function SortableFlexInner({
128128
entering={itemEntering ?? undefined}
129129
exiting={itemExiting ?? undefined}
130130
itemKey={key}
131-
key={key}
132-
layout={itemsLayout ?? undefined}>
131+
key={key}>
133132
{child}
134133
</DraggableView>
135134
))}

packages/react-native-sortables/src/components/SortableGrid.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ function SortableGrid<I>(props: SortableGridProps<I>) {
4444
strategy
4545
},
4646
sharedProps: {
47+
debug,
4748
dimensionsAnimationType,
4849
DropIndicatorComponent,
4950
dropIndicatorStyle,
5051
itemEntering,
5152
itemExiting,
52-
itemsLayout,
5353
overflow,
5454
reorderTriggerOrigin,
5555
showDropIndicator,
@@ -87,6 +87,7 @@ function SortableGrid<I>(props: SortableGridProps<I>) {
8787
<SharedProvider
8888
{...sharedProps}
8989
controlledContainerDimensions={controlledContainerDimensions}
90+
debug={debug}
9091
itemKeys={itemKeys}
9192
initialItemsStyleOverride={
9293
isVertical ? undefined : styles.horizontalStyleOverride
@@ -110,6 +111,7 @@ function SortableGrid<I>(props: SortableGridProps<I>) {
110111
<SortableGridInner
111112
columnGap={columnGapValue}
112113
data={data}
114+
debug={debug}
113115
dimensionsAnimationType={dimensionsAnimationType}
114116
DropIndicatorComponent={DropIndicatorComponent}
115117
dropIndicatorStyle={dropIndicatorStyle}
@@ -118,7 +120,6 @@ function SortableGrid<I>(props: SortableGridProps<I>) {
118120
itemEntering={itemEntering}
119121
itemExiting={itemExiting}
120122
itemKeys={itemKeys}
121-
itemsLayout={itemsLayout}
122123
overflow={overflow}
123124
renderItem={renderItem}
124125
rowGap={rowGapValue}
@@ -135,10 +136,10 @@ type SortableGridInnerProps<I> = DropIndicatorSettings &
135136
Pick<
136137
SortableGridProps<I>,
137138
| 'data'
139+
| 'debug'
138140
| 'dimensionsAnimationType'
139141
| 'itemEntering'
140142
| 'itemExiting'
141-
| 'itemsLayout'
142143
| 'overflow'
143144
| 'renderItem'
144145
| 'rowHeight'
@@ -159,7 +160,6 @@ function SortableGridInner<I>({
159160
itemEntering,
160161
itemExiting,
161162
itemKeys,
162-
itemsLayout,
163163
renderItem,
164164
rowGap,
165165
rowHeight,
@@ -190,7 +190,6 @@ function SortableGridInner<I>({
190190
item={item}
191191
itemKey={key}
192192
key={key}
193-
layout={itemsLayout ?? undefined}
194193
renderItem={renderItem}
195194
style={animatedItemStyle}
196195
/>

packages/react-native-sortables/src/components/shared/AnimatedOnLayoutView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const AnimatedViewWeb = componentWithRef<
2424
onLayout={e => {
2525
const el = (e.nativeEvent as unknown as { target: HTMLElement }).target;
2626
// We want to call onLayout only for displayed views to prevent
27-
// layout animation on navigation between screens
27+
// layout updates on navigation between screens
2828
if (el?.offsetParent) {
2929
onLayout(e);
3030
}

packages/react-native-sortables/src/components/shared/DraggableView/DraggableView.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
type AnimatedStyleProp,
2222
ItemPortalState,
2323
type LayoutAnimation,
24-
type LayoutTransition,
2524
type MeasureCallback
2625
} from '../../../types';
2726
import { getContextProvider } from '../../../utils';
@@ -35,7 +34,6 @@ export type DraggableViewProps = PropsWithChildren<{
3534
itemKey: string;
3635
entering: LayoutAnimation | undefined;
3736
exiting: LayoutAnimation | undefined;
38-
layout: LayoutTransition | undefined;
3937
style?: AnimatedStyleProp;
4038
}>;
4139

packages/react-native-sortables/src/components/shared/DraggableView/ItemCell.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import { type ViewStyle } from 'react-native';
33
import type { AnimatedStyle } from 'react-native-reanimated';
44
import Animated from 'react-native-reanimated';
55

6-
import { IS_WEB } from '../../../constants';
76
import type {
87
AnimatedStyleProp,
98
LayoutAnimation,
10-
LayoutTransition,
119
MeasureCallback
1210
} from '../../../types';
1311
import AnimatedOnLayoutView from '../AnimatedOnLayoutView';
@@ -19,7 +17,6 @@ export type ItemCellProps = PropsWithChildren<{
1917
onMeasure: MeasureCallback;
2018
entering?: LayoutAnimation;
2119
exiting?: LayoutAnimation;
22-
layout?: LayoutTransition;
2320
}>;
2421

2522
export default function ItemCell({
@@ -29,11 +26,10 @@ export default function ItemCell({
2926
entering,
3027
exiting,
3128
itemsOverridesStyle,
32-
layout,
3329
onMeasure
3430
}: ItemCellProps) {
3531
return (
36-
<Animated.View layout={!IS_WEB ? layout : undefined} style={cellStyle}>
32+
<Animated.View style={cellStyle}>
3733
<AnimatedOnLayoutView
3834
entering={entering}
3935
exiting={exiting}

packages/react-native-sortables/src/components/shared/SortableContainer.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@ type AnimatedHeightContainerProps = PropsWithChildren<
3232
DropIndicatorSettings & {
3333
dimensionsAnimationType: DimensionsAnimation;
3434
overflow: Overflow;
35+
debug?: boolean;
3536
style?: StyleProp<ViewStyle>;
3637
}
3738
>;
3839

3940
export default function SortableContainer({
4041
children,
42+
debug,
4143
dimensionsAnimationType,
4244
DropIndicatorComponent,
4345
dropIndicatorStyle,
@@ -67,7 +69,7 @@ export default function SortableContainer({
6769
}
6870

6971
const maybeAnimate = (value: null | number, animate: boolean) =>
70-
animate && (!IS_WEB || shouldAnimateLayout.value) && value !== null
72+
animate && shouldAnimateLayout.value && value !== null
7173
? withTiming(value)
7274
: value;
7375

@@ -140,7 +142,7 @@ export default function SortableContainer({
140142
{children}
141143
</Animated.View>
142144
{/* Renders an overlay view helpful for debugging */}
143-
<DebugOutlet />
145+
{debug && <DebugOutlet />}
144146
</Animated.View>
145147
);
146148
}

packages/react-native-sortables/src/constants/props.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { ViewStyle } from 'react-native';
2-
import { LinearTransition } from 'react-native-reanimated';
32

43
import { DefaultDropIndicator } from '../components/defaults';
54
import type {
@@ -57,7 +56,6 @@ export const DEFAULT_SHARED_PROPS = {
5756
// fixed in `react-native-reanimated` in the future.
5857
itemEntering: IS_WEB ? null : SortableItemEntering,
5958
itemExiting: IS_WEB ? null : SortableItemExiting,
60-
itemsLayout: IS_WEB ? null : LinearTransition,
6159
itemsLayoutTransitionMode: 'all',
6260
onActiveItemDropped: undefined,
6361
onDragMove: undefined,

packages/react-native-sortables/src/providers/layout/flex/FlexLayoutProvider.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,11 @@ const { FlexLayoutProvider, useFlexLayoutContext } = createProvider(
153153

154154
onChange(
155155
props && calculateLayout(props),
156-
// Animate layout only if parent container is not resized
156+
// On web, animate layout only if parent container is not resized
157157
// (e.g. skip animation when the browser window is resized)
158-
IS_WEB &&
159-
(!previousProps?.limits ||
160-
haveEqualPropValues(props?.limits, previousProps?.limits))
158+
!IS_WEB ||
159+
!previousProps?.limits ||
160+
haveEqualPropValues(props?.limits, previousProps?.limits)
161161
);
162162
}
163163
),

packages/react-native-sortables/src/providers/layout/grid/GridLayoutProvider.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ const { GridLayoutProvider, useGridLayoutContext } = createProvider(
134134

135135
onChange(
136136
calculateLayout(props),
137-
// Animate layout only if parent container is not resized
137+
// On web, animate layout only if parent container is not resized
138138
// (e.g. skip animation when the browser window is resized)
139-
IS_WEB &&
140-
(!previousProps?.mainGroupSize ||
141-
props.mainGroupSize === previousProps.mainGroupSize)
139+
!IS_WEB ||
140+
!previousProps?.mainGroupSize ||
141+
props.mainGroupSize === previousProps.mainGroupSize
142142
);
143143
}
144144
),

0 commit comments

Comments
 (0)