Maison >interface Web >js tutoriel >Maîtriser le concept de chargement paresseux dans React Native/ReactJS

Maîtriser le concept de chargement paresseux dans React Native/ReactJS

DDD
DDDoriginal
2024-09-18 15:27:49916parcourir

Le

Lazy Loading est un modèle de conception dans lequel les ressources sont chargées uniquement lorsqu'elles sont nécessaires. Ceci est bénéfique pour améliorer le temps de chargement initial d'une application React Native, réduire la consommation de mémoire et améliorer les performances globales.

Master lazy loading concept in React Native/ReactJS

Pourquoi le chargement paresseux ?

  1. Optimisation des performances : elle évite le chargement de ressources inutiles lors du lancement initial de l'application, ce qui peut réduire considérablement le temps de chargement.
  2. Utilisation réduite de la mémoire : le chargement paresseux empêche de conserver en mémoire des ressources volumineuses telles que des images, des composants ou des bibliothèques externes lorsqu'elles ne sont pas nécessaires.
  3. Expérience utilisateur améliorée : le chargement de ressources à la demande offre une navigation et une interaction plus fluides.

1) Cas d'utilisation de chargement paresseux dans les écrans/composants React Native

  1. Écrans de chargement paresseux (fractionnement de code) :
    Dans React Native, le chargement différé est généralement utilisé pour les composants, en particulier lorsque vous disposez de différents écrans que l'utilisateur ne visite peut-être pas fréquemment. En chargeant paresseusement ces écrans, vous réduisez la taille initiale du bundle.

  2. Chargement paresseux avec React.lazy() et Suspense :
    React a introduit la fonction React.lazy() pour permettre le chargement paresseux des composants. Pour utiliser le chargement paresseux, Suspense est utilisé comme solution de secours jusqu'au chargement du composant.

Utilisation normale

En utilisation normale, toutes les ressources, composants, bibliothèques et données sont chargés dès le démarrage de l'application. Cette approche fonctionne bien pour les petites applications, mais peut devenir inefficace et gourmande en ressources à mesure que l'application se développe, affectant les performances et les temps de chargement.

Exemple : chargement normal d'un composant

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

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

export default App;

Explication :

  • Dans cet exemple, les composants HomeScreen et ProfileScreen sont importés et chargés à l'avance, que l'utilisateur y accède ou non.
  • Cela augmente le temps de chargement initial car tous les composants sont regroupés et chargés en même temps.

Utilisation du chargement paresseux

Avec le chargement paresseux, les composants, les bibliothèques ou les données ne sont chargés qu'en cas de besoin. Cela améliore les performances en réduisant le temps de chargement initial et l'utilisation de la mémoire puisque seules les ressources nécessaires sont chargées à la demande.

Exemple : composants à chargement différé

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;

Explication :

  • Dans cet exemple, HomeScreen et ProfileScreen sont chargés paresseusement à l'aide de React.lazy().
  • Jusqu'à ce que ces composants soient chargés, une solution de secours (ActivityIndicator) est affichée.
  • Cela réduit le temps de chargement initial de l'application puisque les composants ne sont chargés que lorsqu'ils sont rendus.

Différences entre le chargement normal et paresseux

Fonctionnalité Utilisation normale Chargement paresseux ête>
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.
Stratégie de chargement Tout est chargé dès le démarrage de l'application. Les composants, ressources ou données sont chargés uniquement lorsque cela est nécessaire. Temps de chargement initial Plus élevé, car toutes les ressources sont chargées en même temps. Inférieur, car seuls les composants essentiels sont chargés à l'avance. Utilisation de la mémoire Plus élevé, car tous les composants et ressources sont chargés en mémoire. Inférieur, car seuls les composants nécessaires sont chargés en mémoire. Expérience utilisateur Démarrage plus lent mais transitions plus fluides une fois chargé. Démarrage plus rapide mais léger retard lors du chargement des ressources. Idéal pour Petites applications avec des composants limités. Applications volumineuses où tous les composants ne sont pas utilisés initialement. Mise en œuvre Plus simple, car tout est regroupé en même temps. Nécessite la gestion des importations dynamiques et éventuellement le chargement des états.

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.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn