监听关闭事件反应导航

Posted

技术标签:

【中文标题】监听关闭事件反应导航【英文标题】:Listen for dismiss event react navigation 【发布时间】:2020-12-27 17:40:43 【问题描述】:

我在反应导航中有一个模态,写成一个功能组件。在 ios 上,只需向下滑动即可将其关闭。所以我没有后退按钮或任何东西。

我希望能够监听模态框上的关闭事件,因此我可以调用一个函数来清除(redux)状态并在模态框关闭时获取新数据。

navigation.addListener('willBlur') 事件不起作用,因为当我从该模式打开另一个模式时也会触发该事件。

useEffect 看起来很有希望,但我无法让它发挥作用。每次依赖变化时,都会运行效果清理。

    const filters = useSelector(taskFilters);
    const dispatch = useDispatch();
    const isFirstRun = useRef(true);
    useEffect(() => 
        // Skip first render
        if (isFirstRun.current) 
            isFirstRun.current = false;
            return;
        
        // effect cleanup
        return () => 
            dispatch(cleanUpAndFetch(filters));
        ;
    , [filters]);

如果我这样做,它只会在组件卸载时被调用。但是现在我有一个旧版本的过滤器,因为它们不是作为依赖项提供的。如果数据已更改,我只想调用 cleanUpAndFetch,所以我仍然需要处理这个问题

  useEffect(() => 
        return () => 
            dispatch(cleanUpAndFetch(filters));
        ;
    , []);

总结一下。有没有办法?

我使用最新版本的 Expo 和 React Navigation v.4

编辑:

模态是通过导航配置创建的,如下所示:

export const RootStack = createStackNavigator(
    
        Main: 
            screen: RootSwitchStack,
            navigationOptions: 
                headerShown: false,
                headerBackTitleVisible: false
            
        ,
        MyModal,
        ChildModal // Gets opened from MyModal
    ,
    
        initialRouteName: 'Main',
        mode: 'modal',
        defaultNavigationOptions: 
            ...headerSetup,
            ...modalTransitions
        
    
);

MyModal 是我需要类似onRequestClose 的地方

【问题讨论】:

【参考方案1】:

我仍在寻找解决方案,但我已经实施了以下解决方法:

IOS modal 将使用默认转换,只能使用标题返回按钮关闭。

import 
    createStackNavigator,
    TransitionPresets
 from 'react-navigation-stack';
...
export const RootStack = createStackNavigator(
    
        Main: 
            screen: RootSwitchStack,
            navigationOptions: 
                headerShown: false,
                headerBackTitleVisible: false
            
        ,
        MyModal:  
            screen: MyModal,
            navigationOptions: (navigation) => (
                // Our previous were ModalPresentationIOS, but we cannot know
                // when the component has been dismissed, so we use a modal with 
                // back button
                ...TransitionPresets.DefaultTransition,
                headerLeft: () => <HeaderBack navigation=navigation />
            )
        ,
        ChildModal // Gets opened from MyModal
    ,
    
        initialRouteName: 'Main',
        mode: 'modal',
        defaultNavigationOptions: 
            ...headerSetup,
            ...modalTransitions
        
    
);

import  HeaderBackButton  from 'react-navigation-stack';

export const HeaderBack = (
    navigation
: 
    navigation: NavigationStackProp;
) => 
    const filters = useSelector(taskFilters);
    const [initialFilters] = useState(filters);

    const dispatch = useDispatch();

    // We use a bit more complex comparison, but geist of it is the same
    const isFiltersTheSameAsInitial = initialFilters === filters;

    return (
        <HeaderBackButton
            labelVisible=false
            onPress=() => 
                if (!isFiltersTheSameAsInitial) 
                    dispatch(cleanUpAndFetch(filters));
                
                navigation.pop();
            
            tintColor=colors.black
        />
    );
;

【讨论】:

【参考方案2】:

iOS 中的 'Dismiss' 事件可以由 5.x 版本中的 beforeRemove 导航事件/监听器处理(不确定它是否在 4.x 中可用)。

查看这些文档:https://reactnavigation.org/docs/navigation-events/

您可以通过多种方式收听此事件,但这里是一个示例:

screenListeners = 
    focus: () => 
        // do something when screen opens & is focused
    ,
    beforeRemove: () => 
        // do something when scree is closed OR dismissed (in iOS)
    
;

以及稍后渲染时...

<RootStack.Navigator mode="modal">
    <RootStack.Screen
        name="MyScreen"
        component=MyScreenStackNavigator
        listeners=screenListeners
    />
</RootStack.Navigator>

文档中的其他示例:https://reactnavigation.org/docs/navigation-events/#listeners-prop-on-screen

【讨论】:

太棒了!当我们升级到 5.0+ 时会试用它

以上是关于监听关闭事件反应导航的主要内容,如果未能解决你的问题,请参考以下文章

反应组件中的 onDeviceReady 事件监听器

监听浏览器关闭事件

vue 监听浏览器关闭事件

如何在Angular项目里监听页面关闭、跳转事件?

如何使用酶、笑话和反应测试材料设计事件监听器

java自定义事件,线程a如何每一秒钟触发一个事件,然后另一个线程b监听之,并作出反应?