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
相关产品推荐
相关产品推荐

