You need to enable JavaScript to run this app. React Native React Navigation v5 聚焦执行函数与收藏列表更新问题
优惠活动
大模型
产品
解决方案
定价
更多

React Native React Navigation v5 聚焦执行函数与收藏列表更新问题

React Navigation v5 类组件实现屏幕聚焦刷新收藏列表的方案

原代码的核心故障点

  • 空值判断顺序错误:如果Fetch_Favorites()返回null,代码会在执行this.tracks_length = favorites.length时直接触发空引用报错,后续的状态更新逻辑完全中断,导致页面卡在旧状态
  • 导航事件监听缺少清理逻辑:React Navigation v5的addListener会返回带remove方法的订阅句柄,原代码没有在组件卸载时移除监听,长期运行会出现监听泄漏、重复触发、事件绑定失效的问题
  • 嵌套组件的事件接收不稳定:Favorite_Songs_Components是被父页面包裹的子组件,没有直接作为导航器的路由挂载目标,依赖透传的navigation对象绑定focus事件时,容易出现事件触发时机偏移的问题
  • 渲染判断逻辑耦合混乱:原代码将加载占位、空状态、数据列表的判断逻辑揉在同一个分支里,数据拉取完成后容易因为长度比对不通过,一直卡在占位页无法正常渲染

修正后的实现逻辑

  1. 调整空值判断顺序,先校验接口返回值有效性,再读取属性、处理数据
  2. 类组件场景使用官方提供的withNavigationFocus高阶组件,自动给嵌套组件注入isFocused聚焦状态,替代手动绑定focus监听的写法
  3. 新增独立的加载状态字段,和业务状态做分离,避免新旧数据交叉渲染
  4. 简化渲染分支,按加载中、空状态、正常列表的顺序做判断,去掉冗余的长度比对逻辑

修正后的代码示例

父页面Favorites_Songs保持透传必要属性即可:

class Favorites_Songs extends React.Component {
  render() {
    return (
      <Favorite_Songs_Components 
        tracks={this.props.tracks} 
        navigation={this.props.navigation}
      />
    )
  }
}

核心组件Favorite_Songs_Components调整为:

// 引入官方高阶组件
import { withNavigationFocus } from '@react-navigation/core';

class Favorite_Songs_Components extends React.Component {
  state = {
    favorite_songs: "",
    isLoading: true
  }

  componentDidMount() {
    // 首次挂载页面时主动拉取一次数据
    this.get_favorites();
  }

  componentDidUpdate(prevProps) {
    // 仅当页面从失焦状态切换为聚焦状态时,重新拉取最新收藏数据
    if (!prevProps.isFocused && this.props.isFocused) {
      this.get_favorites();
    }
  }

  get_favorites = async() => {
    this.setState({ isLoading: true });
    try {
      const allAvailableTracks = [...(this.props?.tracks || [])];
      const favorites = await Fetch_Favorites();
      
      // 接口返回空值时,直接进入空状态
      if (!favorites) {
        this.setState({ 
          favorite_songs: "empty", 
          isLoading: false 
        });
        return;
      }

      // 过滤出匹配收藏列表的歌曲,适配对象/字符串两种格式的收藏数据
      const matchedFavorites = allAvailableTracks.filter(track => 
        favorites.some(favItem => 
          typeof favItem === 'string' ? favItem === track.title : favItem.title === track.title
        )
      );

      // 过滤后无匹配结果,进入空状态
      if (matchedFavorites.length === 0) {
        this.setState({ 
          favorite_songs: "empty", 
          isLoading: false 
        });
        return;
      }

      this.setState({ 
        favorite_songs: matchedFavorites, 
        isLoading: false 
      });
    } catch (err) {
      // 接口异常时兜底走空状态,避免页面卡死
      this.setState({ 
        favorite_songs: "empty", 
        isLoading: false 
      });
    }
  }

  render() {
    // 加载中展示占位
    if (this.state.isLoading) {
      return <Text>加载中...</Text>
    }

    // 空收藏状态展示提示
    if (this.state.favorite_songs === "empty") {
      return (
        <View style={this.style.container}>
          <Text style={this.style.favorites}>No favorites songs.</Text>
        </View>
      )
    }

    // 正常渲染歌曲列表
    const renderProps = {
      route: "favorites", 
      tracks: this.state.favorite_songs,
      navigation: this.props.navigation,
    }
    return <Tracks {...renderProps} />
  }
}

// 高阶组件包裹后,组件会自动获得isFocused属性,且自动处理监听的绑定与清理
export default withNavigationFocus(Favorite_Songs_Components);

实现注意事项

  • 不需要再手动调用navigation.addListener("focus")绑定事件,withNavigationFocus会在组件生命周期内自动完成监听注册、卸载清理的全流程,不会出现内存泄漏
  • 每次触发数据拉取时先将isLoading设为true,避免旧数据和新拉取的数据交叉渲染导致的显示异常
  • 所有异步接口请求都要做异常兜底,避免接口返回异常时页面白屏、状态永久卡住
  • 嵌套在屏幕内部的非路由组件,不要直接依赖透传的navigation对象绑定导航事件,通过官方高阶组件注入的聚焦状态是React Navigation v5类组件场景下的标准适配方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.09 06:06:10