首页 > 解决方案 > 当用户关闭 React Native 应用程序时将大型状态对象存储在异步存储中

问题描述

我正在构建一个 React Native 应用程序。当用户离开应用程序时,我想通过async-storage.

它似乎在我自己的设备上运行(具有相对强大的 CPU),但在低端移动设备上,它不起作用。我该如何改进它以使其适用于所有设备?

这是我的代码:

// API Helper

import React from 'react';

export const getPhotos = () => sendRequest('/photos');

export const sendRequest = (
  url: string,
  headers?: HeadersInit_ | undefined,
  method = 'GET',
) => {
  url = `https://jsonplaceholder.typicode.com/${url}`;
  return fetch(url, {method: method, headers: headers})
    .then(res => res.json())
    .then(json => json)
    .catch(err => err.message);
};


import React from 'react';
import {
  AppState,
  Button,
  FlatList,
  Image,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import {getPhotos} from './libs/ApiHelper';
import AsyncStorage from '@react-native-async-storage/async-storage';
var sizeof = require('object-sizeof');

let APP_STATE = {
  value: [],
  value2: [],
};

AppState.addEventListener('change', async e => {
  if (e === 'active') {
    console.log('Active');
  } else if (e === 'background') {
    let asyncData = JSON.stringify(APP_STATE);
    await AsyncStorage.setItem('STATE', asyncData, err => {
      console.log("I'm inside setItem " + JSON.stringify(err));
    })
      .then(res => {
        console.log('Done setState in Background :) ' + JSON.stringify(res));
      })
      .catch(err => {
        console.log(
          'Error in setState in Background :( ' + JSON.stringify(err),
        );
      });
    console.log('Background');
  } else if (e === 'extension') {
    console.log('Extension');
  } else if (e === 'inactive') {
    console.log('InActive');
  } else if (e === 'unknown') {
    console.log('Unknown');
  }
});

const appReducer = (state: any, action: any) => {
  const {type, payload} = action;
  const newState = {...state, ...payload};
  APP_STATE = {...APP_STATE, ...newState};
  console.log('State in reducer' + JSON.stringify(newState));
  switch (action.type) {
    case 'resetState':
      return {};
    default:
      return newState;
  }
};

const App = () => {
  const [state, dispatch] = React.useReducer(appReducer, APP_STATE);
  const [ButtonClickable, setButtonClickable] = React.useState(true);

  React.useMemo(() => {
    AsyncStorage.getItem('STATE')
      .then(res => res && JSON.parse(res))
      .then(json => {
        if (!!json) {
          console.log('DATA: ' + JSON.stringify(json));
          dispatch({
            payload: {
              value: json.value,
              value2: json.value2,
            },
          });
        }
      })
      .catch(err => console.log('Error: ' + JSON.stringify(err)));
  }, []);

  React.useEffect(() => {
    console.log(JSON.stringify(state));
  }, [state]);

  const getData = () => {
    setButtonClickable(false);
    getPhotos().then(res => {
      dispatch({
        payload: {
          value: res,
          value2: res,
        },
      });
      setButtonClickable(true);
    });
  };

  return (
    <View style={styles.container}>
      <Button
        title={'Click me to get data :)'}
        disabled={!ButtonClickable}
        onPress={getData}
      />
      <View
        style={{
          marginTop: 50,
          alignItems: 'center',
        }}>
        <Text>Array 1 length: {state.value.length}</Text>
        <Text>Array 2 length: {state.value2.length}</Text>
        <Text style={{marginTop: 100}}>
          Total size of State {(sizeof(state) / 1024 / 1024).toFixed(2)} MB
        </Text>

        <Text
          style={{
            marginTop: 50,
          }}>
          First state is empty so does Array1 and Array2.{'\n'}Tap on Click me
          button and get 5000 objects of photo details from api then you can see
          the array length and state size in Total size. {'\n\n'}Then clear the
          app immedataily
          {'\n'}Reopen the app see the data coming back from Async storage
          {'\n\n'}
          The size after getting from async storage increase don't know why :;
        </Text>
      </View>
    </View>
  );
};

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#333',
    padding: 30,
  },
});

标签: reactjsreact-native

解决方案


推荐阅读