首页 web前端 js教程 掌握 React Native/ReactJS 中的延迟加载概念

掌握 React Native/ReactJS 中的延迟加载概念

Sep 18, 2024 pm 03:27 PM

延迟加载是一种仅在需要时才加载资源的设计模式。这有利于改善 React Native 应用程序的初始加载时间,减少内存消耗,提高整体性能。

Master lazy loading concept in React Native/ReactJS

为什么要延迟加载?

  1. 性能优化:防止应用首次启动时加载不必要的资源,从而显着减少加载时间。
  2. 减少内存使用:延迟加载可防止在不需要时将图像、组件或外部库等大型资源保留在内存中。
  3. 改进的用户体验:按需加载资源提供更流畅的导航和交互。

1) React Native 屏幕/组件中延迟加载的用例

  1. 延迟加载屏幕(代码分割):
    在 React Native 中,延迟加载通常用于组件,特别是当您有用户可能不经常访问的不同屏幕时。通过延迟加载这些屏幕,您可以减小初始包的大小。

  2. 使用 React.lazy() 和 Suspense 进行延迟加载:
    React 引入了 React.lazy() 函数来启用组件的延迟加载。要使用延迟加载,可使用 Suspense 作为后备,直到组件加载。

正常使用

在正常使用中,所有资源、组件、库和数据都会在应用程序启动时预先加载。这种方法适用于小型应用程序,但随着应用程序的增长,可能会变得效率低下且资源密集,从而影响性能和加载时间。

示例:正常组件加载

import React from 'react';
import HomeScreen from './screens/HomeScreen';
import ProfileScreen from './screens/ProfileScreen';

const App = () => {
  return (
    <>
      <HomeScreen />
      <ProfileScreen />
    </>
  );
};

export default App;
登录后复制

说明

  • 在此示例中,HomeScreen 和 ProfileScreen 组件都是预先导入和加载的,无论用户是否导航到它们。
  • 这会增加初始加载时间,因为所有组件都会立即捆绑并加载。

延迟加载用法

通过延迟加载,组件、库或数据仅在需要时加载。由于仅按需加载必要的资源,因此可以通过减少初始加载时间和内存使用来提高性能。

示例:延迟加载组件

import React, { Suspense, lazy } from 'react';
import { ActivityIndicator } from 'react-native';

const HomeScreen = lazy(() => import('./screens/HomeScreen'));
const ProfileScreen = lazy(() => import('./screens/ProfileScreen'));

const App = () => {
  return (
    <Suspense fallback={<ActivityIndicator size="large" color="#0000ff" />}>
      <HomeScreen />
      <ProfileScreen />
    </Suspense>
  );
};

export default App;
登录后复制

说明

  • 在此示例中,HomeScreen 和 ProfileScreen 是使用 React.lazy() 延迟加载的。
  • 在加载这些组件之前,会显示后备(ActivityIndi​​cator)。
  • 这减少了应用程序的初始加载时间,因为组件仅在渲染时加载。

正常加载和延迟加载之间的差异

功能 正常使用 延迟加载 标题>
Feature Normal Usage Lazy Loading
Loading Strategy Everything is loaded upfront when the app starts. Components, resources, or data are loaded only when needed.
Initial Load Time Higher, as all resources are loaded at once. Lower, as only essential components are loaded upfront.
Memory Usage Higher, as all components and resources are loaded into memory. Lower, as only necessary components are loaded into memory.
User Experience Slower startup but smoother transitions once loaded. Faster startup but slight delay when loading resources.
Best for Small applications with limited components. Large applications where not all components are used initially.
Implementation Simpler, as everything is bundled at once. Requires managing dynamic imports and possibly loading states.
加载策略 应用程序启动时,所有内容都会预先加载。 仅在需要时加载组件、资源或数据。 初始加载时间 更高,因为所有资源都会立即加载。 较低,因为仅预先加载必要的组件。 内存使用情况 更高,因为所有组件和资源都加载到内存中。 较低,因为仅将必要的组件加载到内存中。 用户体验 启动速度较慢,但​​加载后过渡更平滑。 启动速度更快,但加载资源时略有延迟。 最适合 组件有限的小型应用程序。 最初并未使用所有组件的大型应用程序。 实施 更简单,因为所有内容都一次性捆绑在一起。 需要管理动态导入和可能的加载状态。 表>

2. Lazy Loading in Navigation (React Navigation):

Lazy loading ensures that screens or components are only mounted when they are accessed (when the user navigates to them), thus improving performance, especially in apps with multiple screens.

Example: Lazy Loading in React Navigation (Stack Navigator)

import React, { Suspense, lazy } from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';
import { ActivityIndicator } from 'react-native';

// Lazy load screens
const HomeScreen = lazy(() => import('./screens/HomeScreen'));
const ProfileScreen = lazy(() => import('./screens/ProfileScreen'));

const Stack = createStackNavigator();

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={() => (
            <Suspense fallback={<ActivityIndicator size="large" color="#0000ff" />}>
              <HomeScreen />
            </Suspense>
          )}
        />
        <Stack.Screen
          name="Profile"
          component={() => (
            <Suspense fallback={<ActivityIndicator size="large" color="#0000ff" />}>
              <ProfileScreen />
            </Suspense>
          )}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;
登录后复制

Explanation:

  • In this example, the HomeScreen and ProfileScreen components are lazily loaded using React.lazy().
  • The Suspense component provides a loading indicator (ActivityIndicator) while the components are being loaded.
  • Screens will only load when the user navigates to them, reducing the initial load time.

3. Lazy Loading Images :

In React Native, lazy loading can be achieved using libraries like react-native-fast-image or manually handling image loading by tracking visibility with tools like IntersectionObserver.

a) Using react-native-fast-image

react-native-fast-image is a performant image component that provides built-in lazy loading.

npm install react-native-fast-image
登录后复制

Example: Lazy Loading Images with react-native-fast-image

import React from 'react';
import { View, ScrollView, Text } from 'react-native';
import FastImage from 'react-native-fast-image';

const LazyLoadingImages = () => {
  return (
    <ScrollView>
      <Text>Scroll down to load images</Text>
      <FastImage
        style={{ width: 200, height: 200 }}
        source={{
          uri: 'https://example.com/my-image1.jpg',
          priority: FastImage.priority.normal,
        }}
        resizeMode={FastImage.resizeMode.contain}
      />
      <FastImage
        style={{ width: 200, height: 200 }}
        source={{
          uri: 'https://example.com/my-image2.jpg',
          priority: FastImage.priority.normal,
        }}
        resizeMode={FastImage.resizeMode.contain}
      />
    </ScrollView>
  );
};

export default LazyLoadingImages;
登录后复制

Explanation:

  • The FastImage component from react-native-fast-image helps with lazy loading. It loads images only when they are about to be displayed.
  • It also provides efficient caching and priority options, improving performance.

b) Manual Lazy Loading (Visibility Tracking)

In cases where you don't want to use a third-party library, you can implement lazy loading by tracking when an image enters the viewport using tools like IntersectionObserver (web) or a custom scroll listener in React Native.

Example: Lazy Loading with Visibility Tracking (using React Native)

import React, { useState, useEffect } from 'react';
import { View, Image, ScrollView } from 'react-native';

const LazyImage = ({ src, style }) => {
  const [isVisible, setIsVisible] = useState(false);

  const onScroll = (event) => {
    // Implement logic to determine if image is visible based on scroll position
    const { y } = event.nativeEvent.contentOffset;
    if (y > 100) { // Example: load image when scrolled past 100px
      setIsVisible(true);
    }
  };

  return (
    <ScrollView onScroll={onScroll} scrollEventThrottle={16}>
      <View>
        {isVisible ? (
          <Image source={{ uri: src }} style={style} />
        ) : (
          <View style={style} />
        )}
      </View>
    </ScrollView>
  );
};

const App = () => {
  return (
    <LazyImage src="https://example.com/my-image.jpg" style={{ width: 200, height: 200 }} />
  );
};

export default App;
登录后复制

Explanation:

  • The LazyImage component only loads the image once the user has scrolled a certain amount (onScroll event).
  • This approach manually tracks the scroll position and loads the image accordingly.

4. Lazy Loading with Redux (Dynamic Reducers) :

When using Redux, you may want to lazy load certain reducers only when necessary, such as for specific screens or features.

  1. Create a function to inject reducers dynamically.
  2. Add the new reducer to the Redux store when needed (e.g., when a user navigates to a new screen).
  3. Remove the reducer when it is no longer needed (optional).

Example: Lazy Loading Reducers in a React Application with Redux

1. Initial Redux Store Setup

Start by setting up a standard Redux store, but instead of adding all reducers upfront, create an injection method.

import { configureStore, combineReducers } from '@reduxjs/toolkit';

const staticReducers = {
  // Add reducers that are needed from the start
};

export const createReducer = (asyncReducers = {}) => {
  return combineReducers({
    ...staticReducers,
    ...asyncReducers,
  });
};

const store = configureStore({
  reducer: createReducer(),
});

// Store injected reducers here
store.asyncReducers = {};

export default store;
登录后复制

In the above code:

  • staticReducers: Contains reducers that are loaded when the app starts.
  • asyncReducers: This object will contain dynamically injected reducers as they are loaded.

2. Dynamic Reducer Injection Method

Create a helper function to inject new reducers dynamically into the store.

// Helper function to inject a new reducer dynamically
export function injectReducer(key, asyncReducer) {
  if (!store.asyncReducers[key]) {
    store.asyncReducers[key] = asyncReducer;
    store.replaceReducer(createReducer(store.asyncReducers));
  }
}
登录后复制

The injectReducer function checks if a reducer has already been added. If not, it injects it into the store and replaces the current root reducer.

3. Loading Reducer When Needed (Lazy Loading)

Imagine you have a new page or feature that needs its own reducer. You can inject the reducer dynamically when this page is loaded.

import { lazy, Suspense, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { injectReducer } from './store';
import featureReducer from './features/featureSlice'; // The reducer for this feature

const FeatureComponent = lazy(() => import('./components/FeatureComponent'));

const FeaturePage = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    injectReducer('feature', featureReducer); // Dynamically load the reducer
  }, [dispatch]);

  return (
    <Suspense fallback={<div>Loading...</div>}>
      <FeatureComponent />
    </Suspense>
  );
};

export default FeaturePage;
登录后复制

Here:

  • When the FeaturePage component is loaded, the injectReducer function adds the featureReducer dynamically to the Redux store.
  • The Suspense component handles lazy loading of the FeatureComponent.

4. Feature Reducer Example

The reducer for the feature is written as usual, using Redux Toolkit.

import { createSlice } from '@reduxjs/toolkit';

const featureSlice = createSlice({
  name: 'feature',
  initialState: { data: [] },
  reducers: {
    setData: (state, action) => {
      state.data = action.payload;
    },
  },
});

export const { setData } = featureSlice.actions;
export default featureSlice.reducer;
登录后复制

Removing a Reducer (Optional)

You might want to remove a reducer when it's no longer needed, for example, when navigating away from a page.

Here’s how you can remove a reducer:

export function removeReducer(key) {
  if (store.asyncReducers[key]) {
    delete store.asyncReducers[key];
    store.replaceReducer(createReducer(store.asyncReducers));
  }
}
登录后复制

You can call this function when a feature or page is unmounted to remove its reducer from the store.


5. Lazy Loading Libraries/Packages:

If you are using heavy third-party libraries, lazy loading them can help optimize performance.

   import React, { useState } from 'react';

   const HeavyComponent = React.lazy(() => import('heavy-library')); // React.lazy(() => import('moment'))

   const App = () => {
     const [showComponent, setShowComponent] = useState(false);

     return (
       <View>
         <Button title="Load Heavy Component" onPress={() => setShowComponent(true)} />
         {showComponent && (
           <Suspense fallback={<Text>Loading...</Text>}>
             <HeavyComponent />
           </Suspense>
         )}
       </View>
     );
   };
登录后复制
  1. Lazy Loading Data: You can also implement lazy loading for data fetching, where data is fetched in chunks or when a user scrolls (infinite scroll).

Example: Lazy Loading Data:

   import React, { useState, useEffect } from 'react';
   import { FlatList, ActivityIndicator, Text } from 'react-native';

   const LazyLoadData = () => {
     const [data, setData] = useState([]);
     const [loading, setLoading] = useState(true);

     useEffect(() => {
       fetch('https://api.example.com/data')
         .then(response => response.json())
         .then(json => {
           setData(json);
           setLoading(false);
         });
     }, []);

     if (loading) {
       return <ActivityIndicator />;
     }

     return (
       <FlatList
         data={data}
         renderItem={({ item }) => <Text>{item.name}</Text>}
         keyExtractor={item => item.id}
       />
     );
   };

   export default LazyLoadData;
登录后复制

Explanation:

  • Fetching data lazily ensures that the app doesn’t load too much data at once, improving performance and reducing bandwidth usage.

Summary of Use Cases:

  1. Screens/Components: Lazy loading React Native screens or components using React.lazy() and Suspense.
  2. Images: Lazy loading images as they enter the viewport to save memory and bandwidth.
  3. Redux Reducers: Injecting reducers dynamically to reduce the initial store size in Redux.
  4. Libraries: Lazily load third-party libraries or packages to reduce the initial bundle size.
  5. Data: Implement lazy loading for large datasets using techniques like pagination or infinite scrolling.

Lazy loading helps improve the performance, memory usage, and user experience of your React Native app, making it more efficient and responsive for users.

以上是掌握 React Native/ReactJS 中的延迟加载概念的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1664
14
CakePHP 教程
1422
52
Laravel 教程
1316
25
PHP教程
1267
29
C# 教程
1239
24
神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript引擎:比较实施 JavaScript引擎:比较实施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

Python vs. JavaScript:学习曲线和易用性 Python vs. JavaScript:学习曲线和易用性 Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

JavaScript:探索网络语言的多功能性 JavaScript:探索网络语言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

如何使用Next.js(前端集成)构建多租户SaaS应用程序 如何使用Next.js(前端集成)构建多租户SaaS应用程序 Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

使用Next.js(后端集成)构建多租户SaaS应用程序 使用Next.js(后端集成)构建多租户SaaS应用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

从C/C到JavaScript:所有工作方式 从C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

See all articles