反应-我的组件在承诺后没有更新状态

时间:2018-11-27 23:13:26

标签: reactjs react-native promise es6-promise react-props

我只是React-Native的初学者,我每天都因somo意外行为而变得疯狂。当然是我的错,我还在学习。 今天,我正努力了解我的代码的作用。

我有一个函数可以调用本地存储中的对象数组。如果我安慰诺言的回应,它会给我一个完美的数组(我认为)。之后,我setState和agin它正确显示在我的控制台上。但是,令我惊讶的是,我的列表组件没有渲染任何东西(它肯定像以前一样工作)。

我将附加我的代码:

/*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 :(得分:1)

解决方案

getAllKeys的{​​{1}}和multiGet返回AsyncStorage。您需要使用await从逻辑中返回promise个已应用的数据。

data

为什么?

它将在不考虑完成Promise功能的承诺之前返回数据。 按以下顺序检查过程号。

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
}

因此,从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变量。

答案 1 :(得分:0)

我已经仔细阅读了您的代码,并提出了一些建议。从本质上讲,您的代码并不是完美的,但是我看不到有什么东西会像您遇到的那样破坏它。问题可能出在您正在寻找的地方之外。调用TagsScreen的地方,或者TagItem。由于尚未更新示例代码,因此使用控制台日志进行的编辑不太清楚从何处调用它们。

一些注意事项可能会帮助您上路。

  • 您可以使用console.log('myMessage', myObject);控制台日志对象,除非您使用JSON.stringify(),否则,如果尝试将对象添加到字符串中,将获得[Object object]
  • 然后在您的Promise中,您不想打两次self.setState。这将使应用两次渲染。您可以在console.log中看到它。两者都可以在一个setState中;一个对象。
  • 设置状态后立即调用console.logs会使状态看起来好像没有被更新。 setState is async,并且在清除事件队列后将被触发。如果要跟踪状态何时更改,请使用react生命周期函数componentDidUpdate(oldProps){}
  • 如果您配对代码以便可以在jsFiddle中运行,这将很有帮助。 This is as far as I got,但效果很好。我提供了很多评论,解释了到底发生了什么。

我将要调试的步骤:

  1. TagList内的deviceList上添加一个console.log,以确保它被调用并且数据在那里。
  2. 确保items是TagItem jsx对象的数组。
  3. 验证TagList html是否已添加到DOM。