在 React/React Native 中,如何防止在选项卡更改、表单更改等时对已检索到的图像发出新的网络请求

Posted

技术标签:

【中文标题】在 React/React Native 中,如何防止在选项卡更改、表单更改等时对已检索到的图像发出新的网络请求【英文标题】:How do I prevent new network requests made for already-retrieved images on tab change, form change etc. in React/React Native 【发布时间】:2021-12-08 06:06:31 【问题描述】:

当我更改页面上的某些内容(例如检查单选按钮或切换选项卡)时,会从浏览器发送新的网络请求以检索图像。我已经在我制作的几个网站上注意到了这一点,但永远不应该有另一个请求;我不会在前端更改这些值时执行fetch。我不明白为什么要再次请求图像。

我附上了一个 gif,显示它发生在我使用 React Native 制作的应用程序中,尽管我也在我的 React 项目中看到过它。当我在右侧的 devtools 中切换选项卡和网络调用时,您可以看到图像闪烁,我也担心性能影响。

如何防止这种情况发生?

对于上下文,我的应用中的数据流如下:

    App.tsx 渲染MainStackNavigator 组件。 在MainStackNavigator 调用firebase 以检索数据(包括图像)。将该数据存储在Context。 在Home.tsx渲染Tabs组件,还要创建一个包含标签数据的数组,即要渲染的组件的名称和组件本身。 在选项卡中根据所选选项卡呈现内容。

Home.tsx

export const Home = (): ReactNode => 
  const scenes = [
    
      key: "first",
      component: EnglishBreakfastHome,
    ,
    
      key: "second",
      component: SecondRoute,
    ,
  ];

  return (
    <View flex=1>
      <Tabs scenes=scenes />
    </View>
  );
;

Tabs.tsx

export const Tabs = ( scenes : TabsProps): ReactNode =>   
  const renderScenes = useMemo(() =>
    scenes.reduce((map, scene) => 
      map[scene.key] = scene.component;
      return map;
    , )
  );

  const renderScene = SceneMap(renderScenes);

  const [index, setIndex] = useState(0);
  const [routes] = useState([
     key: "first", title: "Breakfast" ,
     key: "second", title: "Herbal" ,
  ]);

  const renderTabBar = ( navigationState, position : TabViewProps) => 
    const inputRange = navigationState.routes.map((_, i) => i);
    return (
      <Box flexDirection="row">
        navigationState.routes.map((route, i) => 
          const opacity = position.interpolate(
            inputRange,
            outputRange: inputRange.map((inputIndex) =>
              inputIndex === i ? 1 : 0.5
            ),
          );

          return (
            // Tab boxes and styling
          );
        )
      </Box>
    );
  ;

  return (
    <TabView // using react-native-tab-view
      style= flexBasis: 0 
      navigationState= index, routes 
      renderScene=renderScene
      renderTabBar=renderTabBar
      onIndexChange=setIndex
      initialLayout= width: layout.width 
    />
  );
;

【问题讨论】:

【参考方案1】:

查看react-native-fast-image 之类的内容。甚至是 react-native 文档中的 recommended。

它处理图像的兑现。来自文档:

const YourImage = () => (
    <FastImage
        style= width: 200, height: 200 
        source=
            uri: 'https://unsplash.it/400/400?image=1',
            headers:  Authorization: 'someAuthToken' ,
            priority: FastImage.priority.normal,
        
        resizeMode=FastImage.resizeMode.contain
    />
)

【讨论】:

【参考方案2】:

这里的问题根本不是图像缓存,而是状态管理。

我调用了一个数据库来检索图像,然后将该图像数组存储在包装整个应用程序的AppContext 中。然后,每次我改变状态时,我都会遇到这个问题,因为应用程序正在重新渲染。我做了两件事来消除这个问题:

    Context 分离到单独的存储中,而不仅仅是使用单个全局状态对象。我创建了一个包含所有图像的 ContentContext,以便将状态与其他状态更改分开,因此不会触发重新渲染。

    我使用了useMemo,并重新编写了卡片(您可以在图像中看到)以仅在主图像数据数组更改时更改。这意味着,无论其他状态变量如何变化,该组件都不需要重新渲染,直到图像数组发生变化。

这两种解决方案中的任何一种都可以单独使用,但为了安全起见,我同时使用了这两种解决方案。

【讨论】:

以上是关于在 React/React Native 中,如何防止在选项卡更改、表单更改等时对已检索到的图像发出新的网络请求的主要内容,如果未能解决你的问题,请参考以下文章

React / React Native:如何映射数组并在卡片上显示数据

如何制作需要特定导入的混合包 React/React-Native

在 React/React Native 中,如何防止在选项卡更改、表单更改等时对已检索到的图像发出新的网络请求

如何将更改的状态发送到 react-native 中的组件?

在 React Native 中链接 Pod 的问题

在 react-native-device-info 之后 React Native 代码中断