React Native: анимация при размонтировании

#reactjs #animation #native #react-animated

#reactjs #Анимация #родной #реагирующий -анимированный

Вопрос:

У меня есть компонент, подобный компоненту, который принимает реквизит, и он отображается на основе этого реквизита. Каждый раз, когда этот реквизит изменяется, и компонент повторно отображается, я хочу, чтобы новый компонент появлялся примерно с 20dp, а старый компонент опускался как 20dp и исчезал. Я добился первого (простота ввода), но я не знаю, чего добиться во втором (простота вывода). Я думал, что мне нужно сделать это с помощью метода возврата useEffect (размонтировать), но анимация, похоже, не работает onMount.

 function Component({status}: Props) {
if (status === 'x') return <AnimatedView status={status}><View> xxx <View /><AnimatedView />

<AnimatedView status={status}><View> yyy <View /><AnimatedView />
}
 
 function AnimatedView ({status}: AnimatedProps) {
  const animated = useRef(new Animated.Value(status === 'x' ? 1 : 0))
    .current;

  useEffect(() => {
    const animation = Animated.timing(animated, {
      toValue: status === 'x' ? 1 : 0,
      duration: 200,
      useNativeDriver: true
    });
    animation.start();
    return () => {
      animation.stop();
    };
  }, [animated, status]);
}
 
  const styles = {
    transform: [
      {
        translateY: animated.interpolate({
          inputRange: [0, 1],
          outputRange: status === 'x' ? [20, 0] : [0, 20]
        })
      }
    ],
    opacity: animatedFormHeader.interpolate({
      inputRange: [0, 1],
      outputRange:  status === 'x' ? [0, 1] : [1, 0]
    })
  };
 

Есть ли какой-либо способ добиться этого с помощью анимации ‘react-native’? Должен ли я использовать другой API? Могу ли я привести несколько примеров? На самом деле я думаю, что мне следует переписать все это, потому что я не думаю, что это хорошая идея, что анимация происходит на основе реквизита. Я просто хочу анимировать этот компонент при монтировании и при размонтировании.

Ответ №1:

Я создал компонент на основе того, что я понял из вышесказанного, надеюсь, это то, что вы хотели…

перекус: https://snack.expo.io/yjEX_u_Tu

 
export default ({ status }) => {
  const [text, setText] = useState('');
  const value = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    const animation = Animated.timing(value, {
      toValue: 1,
      duration: 500,
    });
    animation.start(({ finished }) => {
      if (finished) {
        console.log(finished);
        setText(status ? 'Hi' : 'Bye');
        Animated.timing(value, {
          toValue: 0,
          duration: 500,
        }).start();
      }
    });
  }, [status]);

  const translateY = value.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 20],
  });

  const opacity = value.interpolate({
    inputRange: [0, 1],
    outputRange: [1, 0.2],
  });
  return (
    <Animated.View
      style={[styles.container, { opacity, transform: [{ translateY }] }]}>
      <Animated.Text style={{ color: 'white' }}>{text}</Animated.Text>
    </Animated.View>
  );
};
 

Комментарии:

1. это действительно хороший подход, но проблема здесь в том, что у вас есть состояние, которое вы изменяете в useEffect, но в моем случае у меня есть «дочерние элементы», и анимация «облегчения» происходит при монтировании, а не при размонтировании.