You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native如何触发导出函数式组件内的退出动画,需转类组件吗?

方案1:Props状态控制(你构思的方案可直接使用,无需转换为类组件)

你的思路是可行的,只需要修正组件内useEffect的依赖项即可:

1. 修改ModalViewMoveUp.js代码

import React, { useRef, useEffect } from 'react';
import { Animated, Easing } from 'react-native';

// 移除未使用的ExtendedExceptionData导入
export const ModalViewMoveUp = (props) => {
  const moveAnim = useRef(new Animated.Value(900)).current  
  const animIn = Animated.timing(
    moveAnim,
    {
      toValue: 50,
      duration: 1700,
      easing: Easing.elastic(),
      useNativeDriver:false
    }
  )
  const animOut = Animated.timing(
    moveAnim,
    {
      toValue: 1000,
      duration: 1700,
      easing: Easing.elastic(),
      useNativeDriver:false
    }
  )
    
  // 组件挂载时执行进入动画
  useEffect(() => {
    animIn.start();
  }, [animIn])

  // 监听shouldStop属性变化,触发退出动画
  useEffect(() => {
    if(props.shouldStop) {
      // 动画结束后触发父组件传入的回调,可用于销毁模态框等后续操作
      animOut.start(() => props.onAnimEnd?.())
    }
  }, [props.shouldStop, animOut, props])

  return (
    <Animated.View                 
      style={{
        ...props.style,
        marginTop: moveAnim,         
      }}
    >
      {props.children}
    </Animated.View>
  );
}

2. 父组件App.js使用示例(函数式组件写法)

import React, { useState } from 'react';
import { TouchableOpacity, Text } from 'react-native';
// 注意修正导入的组件名,你之前的导入名和使用的组件名不一致
import { ModalViewMoveUp } from './Animations/ModalViewMoveUp'

const App = () => {
  const [shouldStop, setShouldStop] = useState(false)
  const [showModal, setShowModal] = useState(true)

  return (
    <>
      {showModal && <ModalViewMoveUp 
        shouldStop={shouldStop}
        // 动画结束后隐藏模态框
        onAnimEnd={() => setShowModal(false)}
      >
        {/* 其他元素 */}
        <TouchableOpacity onPress={()=> setShouldStop(true)}>
          <Text>取消</Text>
        </TouchableOpacity>
      </ModalViewMoveUp>}
    </>
  )
}
export default App
方案2:useImperativeHandle暴露方法(更灵活的控制方式)

如果不想额外维护状态,可以通过React的forwardRef+useImperativeHandle直接把组件内部的动画方法暴露给父组件调用:

1. 修改ModalViewMoveUp.js代码

import React, { useRef, useEffect, useImperativeHandle, forwardRef } from 'react';
import { Animated, Easing } from 'react-native';

export const ModalViewMoveUp = forwardRef((props, ref) => {
  const moveAnim = useRef(new Animated.Value(900)).current  
  const animIn = Animated.timing(
    moveAnim,
    {
      toValue: 50,
      duration: 1700,
      easing: Easing.elastic(),
      useNativeDriver:false
    }
  )
  const animOut = Animated.timing(
    moveAnim,
    {
      toValue: 1000,
      duration: 1700,
      easing: Easing.elastic(),
      useNativeDriver:false
    }
  )
    
  useEffect(() => {
    animIn.start();
  }, [animIn])

  // 暴露方法给父组件的ref调用
  useImperativeHandle(ref, () => ({
    triggerClose: (callback) => {
      animOut.start(callback)
    }
  }))

  return (
    <Animated.View                 
      style={{
        ...props.style,
        marginTop: moveAnim,         
      }}
    >
      {props.children}
    </Animated.View>
  );
})

2. 父组件App.js使用示例

import React, { useRef, useState } from 'react';
import { TouchableOpacity, Text } from 'react-native';
import { ModalViewMoveUp } from './Animations/ModalViewMoveUp'

const App = () => {
  const modalRef = useRef(null)
  const [showModal, setShowModal] = useState(true)

  const handleCancel = () => {
    // 调用组件内部的关闭动画
    modalRef.current?.triggerClose(() => {
      // 动画结束后隐藏模态框
      setShowModal(false)
    })
  }

  return (
    <>
      {showModal && <ModalViewMoveUp ref={modalRef}>
        {/* 其他元素 */}
        <TouchableOpacity onPress={handleCancel}>
          <Text>取消</Text>
        </TouchableOpacity>
      </ModalViewMoveUp>}
    </>
  )
}
export default App

两种方案都不需要将函数式组件转换为类组件,按需选择即可:如果只是单次控制关闭,方案1更直观;如果需要多次控制动画、或者有其他自定义操作需求,方案2灵活性更高。

内容的提问来源于stack exchange,提问作者Kyriakos Xatzisavvas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:18:04