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

React Native使用useEffect避免byTest重复调用并传值至渲染层

问题背景

以下是abc.tsx文件中的return语句代码:

return (
<ImageBackground
  source={require("../assets/images/abc.png")}
  style={styles.bg}
>
    <CardStack>
      {
         byTest(globalThis.test).map((item) => (
          <Card key={item.id}>
            <CardItemForSwiper
              image={item.image}
              name={item.name}
              description={item.description}
            />
          </Card>
        ))
      }
    </CardStack>
</ImageBackground>
);

上述代码中byTest(globalThis.test)负责从其他ts文件获取数据数组,方法实现如下:

export const byTest = (test: string) => {
const filData = data.filter((rawData) => {
    return rawData.test == test
})
if (filData.length > 0) {
    globalThis.test = test
}
return new Promise((resolve)=>{return resolve(filData)})
}

现存问题

直接在JSX渲染逻辑中调用byTest(globalThis.test),会在组件每次重渲染时重复触发执行,带来不必要的性能开销。

实现目标

即使abc.tsx发生多次重渲染,byTest(globalThis.test)调用也仅触发一次。


实现方案

小提示:你当前实现的byTest内部全是同步执行的过滤逻辑,外层包裹new Promise属于多余操作,可以直接返回过滤后的数组,简化代码同时减少不必要的异步开销。

方案1:useEffect配合状态存储(通用标准方案)

这是最符合React设计逻辑的实现方式,适合绝大多数需要在组件内获取数据的场景,仅在组件首次挂载(或指定依赖变化)时触发数据获取,普通重渲染不会重复执行。

  1. 先引入需要的hooks
    import { useEffect, useState } from 'react';
    
  2. 在组件内部定义状态和数据获取逻辑
    // 存储渲染用的卡片数据
    const [cardList, setCardList] = useState([]);
    
    // 空依赖数组表示仅在组件首次挂载时执行一次
    // 如果需要在globalThis.test变化时重新拉取数据,把依赖数组改为[globalThis.test]即可
    useEffect(() => {
      const fetchData = async () => {
        const res = await byTest(globalThis.test);
        setCardList(res);
      };
      fetchData();
    }, []);
    
  3. 修改渲染逻辑,直接使用预取的状态数据,不要在JSX执行时调用数据方法
    return (
    <ImageBackground
      source={require("../assets/images/abc.png")}
      style={styles.bg}
    >
        <CardStack>
          {cardList.map((item) => (
            <Card key={item.id}>
              <CardItemForSwiper
                image={item.image}
                name={item.name}
                description={item.description}
              />
            </Card>
          ))}
        </CardStack>
    </ImageBackground>
    );
    

方案2:useMemo缓存计算结果(适合纯同步计算场景)

如果你的byTest去掉多余的Promise包装、仅做纯数据过滤、没有修改全局变量这类副作用,可以用useMemo直接缓存计算结果,不需要额外维护state,代码更简洁:

import { useMemo } from 'react';

// 组件内部直接获取缓存的计算结果
const cardList = useMemo(() => {
  return data.filter(rawData => rawData.test === globalThis.test);
}, [globalThis.test]);

该方案下只有globalThis.test的值发生变化时才会重新执行过滤逻辑,普通重渲染会直接复用缓存结果。

方案3:模块级缓存(适合全局通用静态数据场景)

如果过滤后的数据是全局通用的,和单个组件的生命周期无关,可以直接在byTest方法内部加缓存,不管组件重渲染多少次、甚至多个组件同时调用该方法,都只会执行一次过滤逻辑:

// 模块作用域下的缓存变量,全局唯一
let cachedResult = null;
let cachedTestKey = null;

export const byTest = (test: string) => {
  // 命中缓存直接返回缓存结果
  if (cachedTestKey === test && cachedResult) {
    return Promise.resolve(cachedResult);
  }

  const filData = data.filter((rawData) => rawData.test == test)
  if (filData.length > 0) {
    globalThis.test = test
    // 写入缓存
    cachedTestKey = test;
    cachedResult = filData;
  }
  return Promise.resolve(filData)
}

该方案完全不依赖React hooks,不限制调用位置,适合全局固定配置类数据的获取场景。

方案4:专业数据请求库缓存(适合中大型项目复杂场景)

如果项目中有大量数据获取、缓存、同步更新需求,可以直接使用成熟的数据请求库做自动缓存去重,不需要手动写useEffect管理状态,常用的库包括SWR、React Query。这类库会自动对相同key的请求做去重,组件重渲染、跨组件调用相同请求都不会重复触发执行,还自带重试、焦点重验证、过期更新等能力。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:33:33