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

React Native条件渲染时如何避免Banner组件重复渲染?

解决React Native路由切换时Banner组件重复显示的问题

问题原因

路由切换存在动画过渡过程,Dashboard页面的Banner组件在卸载前会短暂保留,而父组件的Banner会提前渲染,导致两个Banner在过渡瞬间重叠显示。

解决方案

通过导航器的焦点事件和切换完成事件,精准控制两个Banner的显示时机,避免时序冲突。

方法1:利用导航事件与焦点状态控制

父组件修改

通过transitionEnd事件确保路由切换完成后再显示父组件的Banner,避免提前渲染:

import { useNavigationState, useNavigationContainerRef } from '@react-navigation/native';
import { useEffect, useState } from 'react';

const App = () => {
  const navigationRef = useNavigationContainerRef();
  const [showParentBanner, setShowParentBanner] = useState(false);
  // 获取当前活跃路由名称
  const currentRouteName = useNavigationState(state => state.routes[state.index]?.name);

  useEffect(() => {
    // 监听路由切换完成事件
    const unsubscribe = navigationRef.addListener('transitionEnd', () => {
      setShowParentBanner(currentRouteName !== 'Dashboard');
    });

    // 初始化显示状态
    setShowParentBanner(currentRouteName !== 'Dashboard');

    return unsubscribe;
  }, [currentRouteName, navigationRef]);

  return (
    <>
      {showParentBanner && <Banner />}
      <Stack.Navigator>
        <Stack.Screen name="Dashboard" component={Dashboard} />
        <Stack.Screen name="Payments" component={Payments} />
        <Stack.Screen name="Invoices" component={Invoices} />
      </Stack.Navigator>
    </>
  );
};

Dashboard组件修改

通过useFocusEffect控制Banner仅在页面获得焦点时显示,失去焦点时立即隐藏:

import { useFocusEffect } from '@react-navigation/native';
import { useState } from 'react';

const Dashboard = () => {
  const [showBanner, setShowBanner] = useState(false);

  useFocusEffect(
    React.useCallback(() => {
      // 页面获得焦点时显示Banner
      setShowBanner(true);
      // 页面失去焦点(即将卸载)时隐藏Banner
      return () => setShowBanner(false);
    }, [])
  );

  return (
    <ScrollView>
      {showBanner && <Banner />}
      {/* 页面其他内容 */}
    </ScrollView>
  );
};

方法2:统一Banner渲染逻辑(可选)

如果Dashboard的Banner不需要跟随ScrollView滚动,可以去掉Dashboard内的Banner,统一在父组件根据路由控制显示:

// 父组件
const App = () => {
  const currentRouteName = useNavigationState(state => state.routes[state.index]?.name);
  return (
    <>
      {/* 所有页面都显示Banner,仅Dashboard路由时隐藏 */}
      {currentRouteName !== 'Dashboard' && <Banner />}
      <Stack.Navigator>
        {/* ...路由配置 */}
      </Stack.Navigator>
    </>
  );
};

// Dashboard组件移除Banner
const Dashboard = () => {
  return (
    <ScrollView>
      {/* 仅保留页面内容 */}
    </ScrollView>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:18:34