I am fading an Image out and once it has completed the fade out animation I unmount it by setting a state to false. Once the state has been set, the Animated component will get unmounted and the error/warning is thrown.
| Screenshot | GIF demo |
|---|---|
|
|
renderMyComponent state, per default it's true) (I'm using <Blurhash> from react-native-blurhash)renderMyComponent to falseThe component gets unmounted, memory gets freed and animation is gone.
Component gets unmounted (I think), but the error Trying to remove a child that doesn't exist gets thrown.
const AnimatedBlurhash = Animated.createAnimatedComponent(Blurhash);
// ...
const [renderBlurhash, setRenderBlurhash] = useState(true);
const blurhashOpacity = useValue(0); // from redash, shoutout @wcandillon
// ...
const onImageLoadEnd = useCallback(() => {
Reanimated.timing(blurhashOpacity, {
duration: 300,
toValue: 0,
easing: Easing.linear,
}).start(() => {
setRenderBlurhash(false);
});
}, [blurhashOpacity]);
// ...
return (
<View>
...
{renderBlurhash && (<AnimatedBlurhash style={{ opacity: blurhashOpacity }} ... />)}
</View>
);
When I wait a short amount of time, e.g. 500ms before setting the boolean state renderBlurhash to false, the error is not thrown. Probably has to do with the async nature of react native, meaning the animation is still not fully disposed in the finished callback which makes immediate unmounting impossible.
Minimal repro:
import React, {useState} from 'react';
import {SafeAreaView, Button} from 'react-native';
import Animated, {timing, Value, Easing} from 'react-native-reanimated';
export default function Example() {
const [showRect, setShowRect] = useState(true);
const opacity = new Value(1);
const t = () =>
timing(opacity, {
duration: 300,
toValue: 0,
easing: Easing.linear,
}).start(() => {
setShowRect(false);
});
return (
<SafeAreaView style={{alignItems: 'center'}}>
<Button onPress={t} title="Opacity" />
{showRect && (
<Animated.View
style={{width: 100, height: 100, backgroundColor: 'green', opacity}}
/>
)}
</SafeAreaView>
);
}
When I wait a short amount of time, e.g. 500ms before setting the boolean state renderBlurhash to false, the error is not thrown. Probably has to do with the async nature of react native, meaning the animation is still not fully disposed in the finished callback which makes immediate unmounting impossible.
The case here is that createAnimatedComponent creates a wrapper that manages the lifecycle of nodes in Reanimated. In componentWillUnmount it detaches nodes from the native side. Backward compatible API of Reanimated also try to detach Value passed as the first argument, but does it after the wrapper has unmounted - it tries detaching detached value resulting in this warning.
Most helpful comment
Minimal repro: