Laggy Layout when using Animated.View with entering animations as a child.
See original GitHub issueI am using entering animations and exiting animations in an
<Animated.View entering={FadeInLeft} exiting={FadeOutLeft}>
{ActiveSearchType.SERIE === activeSearchType && <SerieResultList />}
</Animated.View>
this component is child of a SafeAreaView from ‘react-native-safe-area-context’ library.
import {
Pressable,
SafeAreaView,
StatusBar,
StyleSheet,
Text,
TextInput,
View,
Keyboard,
} from 'react-native';
import {useRecoilValue, useSetRecoilState} from 'recoil';
import {
videoSearchResult,
serieSearchResult,
} from '../../Recoil/SearchPage/SearchPage';
import {
activeCompanySkin,
hideSearchVideo,
} from '../../Recoil/CompanyDetails/ActiveCompany';
import {searchSeries} from '../../network/API/API_serie';
import {searchVideos} from '../../network/API/API_video';
import {strings} from '../../strings/language';
import Animated, {
color,
FadeInLeft,
FadeInRight,
FadeOutLeft,
FadeOutRight,
} from 'react-native-reanimated';
import {useForm, Controller} from 'react-hook-form';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import BottomSheet, {
BottomSheetBackdrop,
BottomSheetFlatList,
BottomSheetView,
useBottomSheetDynamicSnapPoints,
TouchableOpacity,
} from '@gorhom/bottom-sheet';
import {getSearchCategories} from '../../Recoil/SearchPage/SearchPage';
import VideoResultList from '../../components/SearchPageComponents/VideoResulList';
import SerieResultList from '../../components/SearchPageComponents/SerieResultList';
enum ActiveSearchType {
VIDEO = 'video',
SERIE = 'serie',
}
const SearchPage = () => {
const setVideoSearchResult = useSetRecoilState(videoSearchResult);
const setSerieSearchResult = useSetRecoilState(serieSearchResult);
const searchCategories = useRecoilValue(getSearchCategories);
const [selectedCategoryId, setSelectedCategoryId] = useState<number | null>(
null,
);
const [activeSearchType, setActiveSearchType] = useState<ActiveSearchType>(
ActiveSearchType.SERIE,
);
const searchRef: any = React.useRef();
const Skin = useRecoilValue(activeCompanySkin);
const Strings = useRecoilValue(strings);
const {
_backgroundColor,
alphaColor,
fontColor,
primaryColor,
buttonTextColor,
} = Skin;
//ENIVRONMENT
const {
control,
handleSubmit,
formState: {errors},
} = useForm({
defaultValues: {
search: '',
},
});
const onSubmit = async ({search}: {search: string}) => {
console.log(search);
const searchPromises = await Promise.all([
searchSeries(
1,
search,
selectedCategoryId !== null ? [selectedCategoryId] : [],
),
searchVideos(
1,
search,
selectedCategoryId !== null ? [selectedCategoryId] : [],
),
]);
setSerieSearchResult(searchPromises[0]);
setVideoSearchResult(searchPromises[1]);
};
React.useEffect(() => {
searchRef?.current.focus();
const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
bottomSheetRef?.current?.close();
});
return () => {
showSubscription.remove();
};
}, []);
//BOTTOMSHEET_
const bottomSheetRef = React.useRef<BottomSheet>(null);
const data = useMemo(() => searchCategories, []);
const initialSnapPoints = useMemo(() => ['25%', 'CONTENT_HEIGHT'], []);
const {
animatedHandleHeight,
animatedSnapPoints,
animatedContentHeight,
handleContentLayout,
} = useBottomSheetDynamicSnapPoints(initialSnapPoints);
const handleSheetChanges = useCallback((index: number) => {
if (index === 1 || index === 0) {
Keyboard.dismiss();
} else {
}
}, []);
const renderBackdrop = useCallback(
props => (
<BottomSheetBackdrop
{...props}
disappearsOnIndex={-1}
appearsOnIndex={1}
/>
),
[],
);
const SwipeableResultList = () => {
return (
<View style={{flex: 1, marginTop: 40}}>
<Animated.View entering={FadeInLeft} exiting={FadeOutLeft}>
{ActiveSearchType.SERIE === activeSearchType && <SerieResultList />}
</Animated.View>
<Animated.View entering={FadeInRight} exiting={FadeOutRight}>
{ActiveSearchType.VIDEO === activeSearchType && <VideoResultList />}
</Animated.View>
</View>
);
};
return (
<>
<StatusBar
animated={true}
backgroundColor={_backgroundColor}
barStyle={fontColor}
/>
<SafeAreaView
style={{
flex: 1,
backgroundColor: _backgroundColor,
flexDirection: 'column',
padding: 15,
}}>
<View>
<Controller
control={control}
render={({field: {onChange, onBlur, value}}) => (
<View
style={[
styles.searchInputContainer,
{
borderColor: fontColor,
},
]}>
<View
style={{
flex: 4,
}}>
<TextInput
style={[
styles.input,
{
color: fontColor,
},
]}
returnKeyType={'search'}
ref={searchRef}
onBlur={onBlur}
onChangeText={onChange}
value={value}
placeholder={Strings.SearchPlaceholder}
placeholderTextColor="#A9A9AC"
autoCapitalize={'none'}
autoCorrect={false}
onSubmitEditing={handleSubmit(onSubmit)}
/>
</View>
<View
style={{
flex: 2,
justifyContent: 'center',
alignItems: 'center',
}}>
<Pressable
onPress={() => {
bottomSheetRef?.current?.expand();
}}
style={({pressed}) => [
{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: _backgroundColor,
borderWidth: 2,
borderColor: fontColor,
borderRadius: 30,
width: '100%',
height: '100%',
opacity: pressed ? 0.7 : 1,
},
]}>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text
style={{
color: buttonTextColor,
fontSize: 14,
marginRight: 5,
}}>
{Strings.SearchCategory}
</Text>
<FontAwesome5
name={'chevron-down'}
solid
color={fontColor}
size={14}
/>
</View>
</Pressable>
</View>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<FontAwesome5
name={'search'}
solid
color={fontColor}
size={24}
/>
</View>
</View>
)}
name="search"
/>
</View>
<View
style={{
marginTop: 20,
flexDirection: 'row',
}}>
<Pressable
onPress={() => {
setActiveSearchType(ActiveSearchType.SERIE);
}}
style={{
flex: 3,
borderWidth: 2,
borderColor:
activeSearchType === ActiveSearchType.SERIE
? primaryColor
: fontColor,
backgroundColor:
activeSearchType === ActiveSearchType.SERIE
? primaryColor
: _backgroundColor,
borderRadius: 20,
paddingVertical: 5,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text
style={{
color:
activeSearchType === ActiveSearchType.SERIE
? buttonTextColor
: fontColor,
textAlign: 'center',
}}>
Serie
</Text>
</Pressable>
<Pressable
onPress={() => {
setActiveSearchType(ActiveSearchType.VIDEO);
}}
style={{
flex: 3,
borderWidth: 2,
borderColor:
activeSearchType === ActiveSearchType.VIDEO
? primaryColor
: fontColor,
backgroundColor:
activeSearchType === ActiveSearchType.VIDEO
? primaryColor
: _backgroundColor,
borderRadius: 20,
paddingVertical: 5,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text
style={{
color:
activeSearchType === ActiveSearchType.VIDEO
? buttonTextColor
: fontColor,
textAlign: 'center',
}}>
Video
</Text>
</Pressable>
</View>
<SwipeableResultList />
<BottomSheet
ref={bottomSheetRef}
index={-1}
snapPoints={animatedSnapPoints}
handleHeight={animatedHandleHeight}
contentHeight={animatedContentHeight}
enablePanDownToClose={true}
backdropComponent={renderBackdrop}
onChange={handleSheetChanges}
handleStyle={{backgroundColor: fontColor}}
backgroundStyle={{backgroundColor: fontColor}}>
<BottomSheetView
style={{
flex: 1,
backgroundColor: _backgroundColor,
padding: 6,
margin: 6,
}}
onLayout={handleContentLayout}>
<BottomSheetFlatList
style={{width: '100%'}}
data={data}
keyExtractor={(i: any) => i.name_ml}
renderItem={({item}: {item: any}) => {
return (
<TouchableOpacity
onPress={() => {
setSelectedCategoryId(item.id);
bottomSheetRef.current?.close();
}}>
<View
style={{
flex: 1,
backgroundColor: _backgroundColor,
padding: 6,
margin: 6,
flexDirection: 'row',
}}>
<View
style={{
flex: 0.5,
justifyContent: 'flex-end',
alignItems: 'center',
}}>
<View
style={{
height: 16,
width: 16,
borderWidth: 2,
borderRadius: 30,
borderColor: fontColor,
justifyContent: 'center',
alignItems: 'center',
}}>
<View
style={{
display:
selectedCategoryId === item.id
? 'flex'
: 'none',
backgroundColor: fontColor,
height: 10,
width: 10,
borderRadius: 30,
}}
/>
</View>
</View>
<View
style={{
flex: 5.5,
alignItems: 'center',
}}>
<Text
style={{
width: '100%',
textAlign: 'left',
color: fontColor,
}}>
{item.name}
</Text>
</View>
</View>
</TouchableOpacity>
);
}}
/>
</BottomSheetView>
</BottomSheet>
</SafeAreaView>
</>
);
};
const styles = StyleSheet.create({
input: {},
searchInputContainer: {
borderWidth: 2,
borderRadius: 30,
padding: 10,
flexDirection: 'row',
},
});
export default SearchPage;
When using animations in entering on any of the views inside the layout is not behaving as expected. The Layout becomes laggy moving up in a non displayed area, under the navigation Header
Expected behavior
Should behave as when i’m not using entering animations.
Actual behavior & steps to reproduce
Layout problems pushing my View and making it laggy
Snack or minimal code example
Package versions
name | version |
---|---|
react-native | 0.66.4 |
react-native-reanimated | ^2.3.1 |
NodeJS | v16.9.1. |
Xcode | 13.2.1 |
Java | java version “15” 2020-09-15 |
Affected platforms
- Android
- iOS
- Web
Issue Analytics
- State:
- Created 2 years ago
- Comments:8
Top Results From Across the Web
Why do these constraints seem to lag when animated?
When using layoutIfNeeded() , it should be called on the superview of the view containing the constraints. In my situation, I put the...
Read more >Reveal or hide a view using animation - Android Developers
There are three common animations to use when showing or hiding a view. You can use the circular reveal animation, a crossfade animation, ......
Read more >Animated - React Native
Value , hook it up to one or more style attributes of an animated component, and then drive updates via animations using Animated.timing()...
Read more >CSS and JavaScript animation performance - MDN Web Docs
Browsers are able to optimize rendering flows. In summary, we should always try to create our animations using CSS transitions/animations ...
Read more >Fixed issues in Animate release - Adobe Support
Animate 2022 (version 22.0.5) · Video export or Publishing takes too long and the output doesn't match with the stage if layer effects...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I think reanimated is tested on a powerful computer and a powerful simulator or cell phone. It is better that you do your animations.
I ned to be more specific. Basically at the end i ended up with custom headers with a specific height:number not percentage or flexbox. So every screen renders a custom header, and this worked quite fine for me.
When using specific height with default header with custom components inside, it used to be glitchy, it seems that default header works fine only when changing little stuff like title, or back button.
For example: I had a logo that i need to show in every page in the center of the header and this was causing a strange behaviour