Где вызвать функцию AsyncStorage.GetItem() для загрузки сохраненных данных в react-native?

#javascript #react-native

#javascript #react-native

Вопрос:

Я сохранил одни данные внутри одного класса моего проекта react-native. С сохранением данных я запускаю новый экран. На этом экране я извлекаю эти сохраненные данные. Для этой цели я вызываю функцию AsyncStorage.GetItem(‘token’) внутри функции рендеринга.

Вот код для этого класса-

 import React from 'react';
import { StyleSheet, Text, View, Image, AsyncStorage } from 'react-native';
import {Icon, Button, Container, Header, Content, Left} from 'native-base';
import CustomHeader from './CustomHeader';

 class NoteMeHome extends React.Component {
  state = {
    text:'',
    storedValue:'',
    getValue: ''
  };

  static navigationOptions = ({navigation}) => ({
    title: "Home",
    headerLeft: <Icon name="ios-menu" style={{paddingLeft:10}}
    onPress={()=>navigation.navigate('DrawerOpen')}/>,

    drawerIcon: 

    <Image source={require('../assets/icon.png')}
            style={styles.icon}
    />
  })

  render() {
    const {storedValue} = this.state;

    AsyncStorage.getItem('token').then(value =>
      //AsyncStorage returns a promise so adding a callback to get the value
      this.setState({ getValue: value })
      //Setting the value in Text 
    );

    return(
      <Container>
        <CustomHeader
          title="Home"
          drawerOpen={()=>this.props.navigation.navigate('DrawerOpen')}
        />
        <Content contentContainerStyle={{flex:1, alignItems:'center', 
        justifyContent:'center', padding:10}}>
        <Button full onPress={()=> this.props.navigation.navigate('Settings')}>
          <Text style={{color:'white'}}>{storedValue}</Text>
        </Button>
        <Text>{this.state.getValue}</Text>
        </Content>
      </Container>
    )
  }

}

const styles = StyleSheet.create({
  icon:{
    height: 24,
    width: 24
  }
})
export default NoteMeHome;
  

После этого, во время запуска проекта в вышеупомянутом классе, когда я нажимаю на любой из элементов моего ящика, чтобы перейти к другому экрану, в консоли отображается следующая ошибка-

проблема: не удается вызвать setState (или forceUpdate) для размонтированного компонента. Это не-операция, но это указывает на утечку памяти в вашем приложении. Чтобы исправить, отмените все подписки и асинхронные задачи в методе componentWillUnmount.

Я предполагаю, что что-то идет не так с вызовом функции AsyncStorage.GetItem (‘token’), потому что, если я удалю функцию, она не покажет никакого предупреждения.

Итак, было бы очень приятно, если бы кто-нибудь помог мне узнать, где я должен вызвать следующий код-

 AsyncStorage.getItem('token').then(value =>
  //AsyncStorage returns a promise so adding a callback to get the value
  this.setState({ getValue: value })
  //Setting the value in Text 
);
  

чтобы удалить предупреждение?

Комментарии:

1. Я думаю, у вас больше проблема с философией React. Вам следует попробовать использовать перехват для установки состояния или даже лучше, на мой взгляд: поместите ваш вызов «AsyncStorage» в функцию componentDidUpdate(). Проблема в том, что каким-то образом запускается последний рендеринг, компонент размонтирован, но ваш асинхронный вызов, инициированный при последнем рендеринге, продолжается, пока ваш компонент размонтирован.

2. Не могли бы вы, пожалуйста, дополнить свое описание кодом, потому что я не понимаю его должным образом. Я вызвал AsyncStorage вне функции рендеринга внутри функции componentDidUpdate(). Но на этот раз она не извлекает значение.

Ответ №1:

Asif,

Вот что я имел в виду :

 import React from 'react';
import { StyleSheet, Text, View, Image, AsyncStorage } from 'react-native';
import {Icon, Button, Container, Header, Content, Left} from 'native-base';
import CustomHeader from './CustomHeader';

 class NoteMeHome extends React.PureComponent {
  state = {
    text:'',
    storedValue:'',
    getValue: ''
  };

  static navigationOptions = ({navigation}) => ({
    title: "Home",
    headerLeft: <Icon name="ios-menu" style={{paddingLeft:10}}
    onPress={()=>navigation.navigate('DrawerOpen')}/>,

    drawerIcon: 

    <Image source={require('../assets/icon.png')}
            style={styles.icon}
    />
  });
  
  componentDidMount() {
    const token = await AsyncStorage.getItem('token');
    this.setState({ getValue: token });
  }

  render() {
    const {storedValue, getValue} = this.state;
    return(
      <Container>
        <CustomHeader
          title="Home"
          drawerOpen={()=>this.props.navigation.navigate('DrawerOpen')}
        />
        <Content contentContainerStyle={{flex:1, alignItems:'center', 
        justifyContent:'center', padding:10}}>
        <Button full onPress={()=> this.props.navigation.navigate('Settings')}>
          <Text style={{color:'white'}}>{storedValue}</Text>
        </Button>
        <Text>{getValue}</Text>
        </Content>
      </Container>
    )
  }

}

const styles = StyleSheet.create({
  icon:{
    height: 24,
    width: 24
  }
})
export default NoteMeHome;  

Я не знаю, следует ли в вашем случае на самом деле пытаться обработать обновление компонента, поскольку у вас нет никаких реквизитов.

С уважением,

Ответ №2:

ИМО вам следует использовать componentDidMount для всего, что вы хотите сделать в начале экрана. Чтобы использовать, AsyncStorage помните, что это asynchronous функция, поэтому вам нужно дождаться завершения функции, чтобы вы могли получить значение.

Для получения дополнительной информации о компонентах react native, пожалуйста, смотрите это

Для получения дополнительной информации об «ожидании» использования AsyncStorage, async пожалуйста, смотрите эти примеры

Ответ №3:

Компонент react render() всегда должен оставаться чистым. Никогда не следует устанавливать состояние в функции рендеринга, это очень плохая практика, в простом компоненте это могло бы работать нормально. Это работает только из-за асинхронности.

Вы должны использовать componentDidMount метод жизненного цикла для извлечения данных из локального хранилища.

 componentDidMount() {
    const token = await AsyncStorage.getItem('token');
    this.setState({ getValue: token });
}