Реагируйте - Мой компонент не обновляет состояние после обещания - PullRequest
0 голосов
/ 28 ноября 2018

Я всего лишь новичок в React-Native и каждый день схожу с ума от неожиданного поведения.Конечно, это моя вина, я все еще учусь.Сегодня я изо всех сил пытаюсь понять, что происходит с моим кодом.

У меня есть функция, которая вызывает массив объектов в моем локальном хранилище.Если я утешу ответ от обещания, это даст мне идеальный массив (я думаю).После этого я установил и снова включил его на моей консоли.Но, к моему удивлению, мой компонент списка ничего не рендерит (и он наверняка работает так, как раньше).

Я добавлю свой код:

/*FUNCTION FILE*/

getAllData: async () => {
    var data = [{id:null, address:null, name:null}];
    AsyncStorage.getAllKeys((err, keys) => {
      AsyncStorage.multiGet(keys, (err, stores) => {
        stores.map((result, i, store) => {
          // get at each store's key/value so you can work with it
          var key = store[i][0];
          var value = store[i][1];
          data[i] = {id: i, address: key, name: value}
        });
      });
    });
  return data},

//MAIN FILE (DAD COMPONENT)


import React, { Component } from 'react';
import { View, Text } from 'react-native';

import NewTagButton from '../components/NewTagButton';



import TagList from '../components/TagList';
import storage from '../functions/Storage';
import { Object } from 'core-js';
//import { TagPosition } from '../functions/GPSTag'

class TagsScreen extends Component {
  constructor(props) {
    super(props);
    
    this.state = {message:"",
                  pairedDevices: [], 
  
    };
  }

  componentDidMount () {
  var self = this;
  storage.getAllData() //tem que esperar a promise
        .then(function (devices) {
            self.setState({message: "Scaneamento finalizado."});
            self.setState({pairedDevices: devices});
            
        console.log("devices")
        console.log(devices)
        console.log("State")
        console.log(self.state.pairedDevices)
      })
        .catch(()=> console.log("Promise rejected"))
  }

  

  render() {
    
    return (
      <View>
        <Text>{this.state.message}</Text>
        <TagList  devices = {this.state.pairedDevices} origem = 'MyTag'/>
        <NewTagButton/>
      </View>
    );
  }
}

export default TagsScreen;

LIST COMPONENT THAT SHOULD RENDER THE LIST

import React from 'react';
import { View,  StyleSheet } from 'react-native';

import TagItem from '../components/TagItem'


const TagList = props => {

    const devicesList = props.devices;
    const origem = props.origem;

    //aqui a gente vai passar device a device para a page TagItem
    const items = devicesList.map((device) => 
    
        <TagItem 
            key = {device.address}       
            address = {device.address} 
            name = {device.name}
            origem = {origem}/>
     );


     return (
        <View key = {items} styles = {styles.container}>
          {items}
        </View>
      );
}



const styles = StyleSheet.create({
    container : {
        alignItems:'center',
        
  
    }
  })

export default TagList;

Спасибо.

РЕДАКТИРОВАТЬ: я поместил несколько журналов между компонентами, изображение на URL, потому что у меня недостаточно репутацииха-ха

Console.Log

EDIT2:

Я только что создал глупую кнопку, чтобы установить состояние только с помощью строки.После изменения этого состояния приложение отображает список.Конечно, это проблема с обещанием, кто-то может мне помочь?=]

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Решение

getAllKeys и multiGet из AsyncStorage возвращаются promise.Вам нужно использовать await для возврата data приложенных данных из вашей логики.

getAllData = async () => {
    var data = [{id:null, address:null, name:null}];
    await AsyncStorage.getAllKeys(async (err, keys) => { // This is async function. 
      await AsyncStorage.multiGet(keys, (err, stores) => { // This is async function also. 
        stores.map((result, i, store) => {
          // get at each store's key/value so you can work with it
          var key = store[i][0];
          var value = store[i][1];
          data[i] = {id: i, address: key, name: value}
        });
      });
    });
    console.log(data); // Check your data. 
    return data
}

Почему?

Он вернет данные до завершения обещания функции Promise без беспокойства.Проверьте номер процесса по порядку ниже.

getAllData = async () => {
    var data = [{id:null, address:null, name:null}]; // 1. 

    AsyncStorage.getAllKeys((err, keys) => { // 4. there is no async await decoration
      AsyncStorage.multiGet(keys, (err, stores) => { // 3. there is no async await decoration 
        stores.map((result, i, store) => {
          // get at each store's key/value so you can work with it
          var key = store[i][0];
          var value = store[i][1];
          data[i] = {id: i, address: key, name: value}
        });
      });
    });

    return data // 2. 
}

Таким образом, данные имеют null при возврате из функции getAllData.После этого функции AsyncStorage будут применены к переменной data.

0 голосов
/ 28 ноября 2018

Я некоторое время просматривал ваш код и придумал несколько вещей.По сути, ваш код не идеален, но я не вижу ничего, что могло бы сломать его, как вы испытываете.Вероятно, проблема находится за пределами, где вы смотрите.Либо где TagsScreen вызывается, либо TagItem.Ваше редактирование с помощью журнала консоли не очень понятно, откуда они вызываются, поскольку ваш пример кода не был обновлен.

Несколько заметок, которые могут помочь вам в вашем пути.

  • Вы можете поддерживать объекты журнала с помощью console.log('myMessage', myObject); Если вы не используете JSON.stringify(), вы получите [Object object], если попытаетесь добавить объект в строку.
  • В вашем Promise.then вам не нужно звонить self.setState дважды.Это сделает приложение дважды.Вы можете видеть это в вашем console.log .Оба из них могут быть в одном setState;один объект.
  • Вызов вашего console.logs сразу после того, как вы установите состояние, создаст впечатление, что состояние не обновляется. setState является асинхронным и будет запущен после очистки очереди событий.Если вы хотите отслеживать, когда состояние изменилось, используйте функцию жизненного цикла реакции componentDidUpdate(oldProps){}
  • . Было бы полезно, если вы спарили свой код, чтобы его можно было запустить в jsFiddle. Это насколько я получил , но работает отлично.Я включил множество комментариев, которые объясняют, что именно происходит.

Шаги, которые я бы предпринял для отладки:

  1. Добавьте console.log в deviceList внутри TagList, чтобыубедитесь, что он вызывается и данные есть.
  2. Убедитесь, что items является массивом объектов TagItem jsx.
  3. Убедитесь, что HTML TagList добавляется в DOM.
...