【问题标题】:React - My component is not updating the state after a promiseReact - 我的组件在承诺后没有更新状态
【发布时间】:2019-04-29 18:48:24
【问题描述】:

我只是 React-Native 的初学者,我每天都因为一些意想不到的行为而变得疯狂。当然是我的错,我还在学习。 今天我很难理解我的代码发生了什么。

我有一个函数可以调用本地存储上的对象数组。如果我从承诺中得到回应,它会给我一个完美的数组(我认为)。之后我 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

编辑2:

我刚刚创建了一个愚蠢的按钮来设置一个状态只是用一个字符串。在此状态更改后,应用程序会呈现列表。肯定是一个承诺问题,有人可以帮助我吗? =]

【问题讨论】:

  • 我认为您需要将 key = {items} 更改为其他内容,以便重新渲染。
  • 能否在 taglist 函数中放置一些日志以查看该函数是否被执行?这样就更容易找出问题所在。
  • Colin,我尝试更改密钥,但没有任何反应。实际上,这个组件在另一个地方被使用并且它正在工作。我认为问题在于对象处理,也许我对对象索引感到困惑......

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


【解决方案1】:

我已经浏览了您的代码一段时间并想出了一些东西。从本质上讲,您的代码并不完美,但我没有看到任何会破坏它的东西,就像您正在经历的那样。问题可能出在您正在寻找的地方之外。在调用TagsScreenTagItem 的位置。由于您的示例代码尚未更新,您对控制台日志的编辑不是很清楚从哪里调用它们。

一些可以帮助您上路的注意事项。

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

调试步骤:

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

【讨论】:

    【解决方案2】:

    解决方案

    AsyncStoragegetAllKeysmultiGet 是返回 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 函数的 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. 
    }
    

    因此,当从getAllData 函数返回时,数据有null。之后,AsyncStorage 的函数将应用于data 变量。

    【讨论】:

    • 我同意你的观点,这是关于承诺的事情,但我不能在那里称之为“等待”。它弹出一个错误,说它不是同步功能......(wtf)
    • 你检查getAllKeys回调前的装饰异步了吗?
    猜你喜欢
    • 2021-08-26
    • 2019-03-10
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 2019-12-29
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    相关资源
    最近更新 更多