Skip to content

Commit a8b0798

Browse files
authored
ExpandableSection - fix inner component's animation not working (#2990)
1 parent 92df880 commit a8b0798

File tree

1 file changed

+34
-21
lines changed

1 file changed

+34
-21
lines changed

src/components/expandableSection/index.tsx

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React, {useMemo} from 'react';
2-
import {LayoutAnimation, StyleSheet} from 'react-native';
1+
import React, {useMemo, useState} from 'react';
2+
import {LayoutChangeEvent, StyleSheet} from 'react-native';
3+
import {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
34
import View from '../view';
45
import TouchableOpacity from '../touchableOpacity';
5-
import {useDidUpdate} from 'hooks';
66

77
export type ExpandableSectionProps = {
88
/**
@@ -38,44 +38,57 @@ export type ExpandableSectionProps = {
3838
*/
3939

4040
function ExpandableSection(props: ExpandableSectionProps) {
41-
const {expanded, sectionHeader, children, top, testID} = props;
41+
const {expanded, sectionHeader, onPress, children, top, testID} = props;
42+
const [height, setHeight] = useState(0);
43+
const animatedHeight = useSharedValue(0);
4244

43-
/**
44-
* TODO: move to reanimated LayoutAnimation after updating to version 2.3.0
45-
* after migration, trigger the animation only in useDidUpdate.
46-
*/
47-
const animate = () => {
48-
LayoutAnimation.configureNext({...LayoutAnimation.Presets.easeInEaseOut, duration: 300});
49-
};
45+
const onLayout = (event: LayoutChangeEvent) => {
46+
const onLayoutHeight = event.nativeEvent.layout.height;
5047

51-
const onPress = () => {
52-
props.onPress?.();
53-
animate();
48+
if (onLayoutHeight > 0 && height !== onLayoutHeight) {
49+
setHeight(onLayoutHeight);
50+
}
5451
};
5552

56-
useDidUpdate(() => {
57-
animate();
58-
}, [expanded]);
53+
const expandableStyle = useAnimatedStyle(() => {
54+
animatedHeight.value = expanded ? withTiming(height) : withTiming(0);
55+
56+
return {
57+
height: animatedHeight.value
58+
};
59+
}, [expanded, height]);
60+
61+
const style = useMemo(() => [styles.hidden, expandableStyle], [expandableStyle]);
5962

6063
const accessibilityState = useMemo(() => {
6164
return {expanded};
6265
}, [expanded]);
6366

67+
const renderChildren = () => {
68+
return (
69+
<View reanimated style={style}>
70+
<View absH onLayout={onLayout}>
71+
{children}
72+
</View>
73+
</View>
74+
);
75+
};
76+
6477
return (
65-
<View style={styles.container}>
66-
{top && expanded && children}
78+
<View style={styles.hidden}>
79+
{top && renderChildren()}
6780
<TouchableOpacity onPress={onPress} testID={testID} accessibilityState={accessibilityState}>
6881
{sectionHeader}
6982
</TouchableOpacity>
70-
{!top && expanded && children}
83+
{!top && renderChildren()}
7184
</View>
7285
);
7386
}
7487

7588
export default ExpandableSection;
7689

7790
const styles = StyleSheet.create({
78-
container: {
91+
hidden: {
7992
overflow: 'hidden'
8093
}
8194
});

0 commit comments

Comments
 (0)