简体   繁体   English

React Native:调用try-catch函数时setState不起作用

[英]React Native: setState doesn't work when calling try-catch function

I tried to call APP with this code imported from another file and it worked fine: 我试图用从另一个文件导入的此代码调用APP,它工作正常:

import FormData from 'FormData';
import AsyncStorage from '@react-native-community/async-storage';

let formData = new FormData();

formData.append('userId', '1'); // < this is what I want to change
formData.append('key', '***'); //my key

 export function getScoreFromAPI () {
   return fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
                 method : 'POST',
                 headers : {
                   'Accept': 'application/json',
                   'Content-Type': 'multipart/form-data'
                 },
                 body : formData
             } )
       .then((response) => {
          return response.json()
       })
    .catch((error) => console.log("l'erreure est:  " + error))
 }

but now I want to change my userId from 1 to an constante from Asyncstorage, so I decide to change my code to this: 但是现在我想将我的userId从1更改为Asyncstorage的常量,因此我决定将代码更改为此:

  constructor(props) {
      super(props)
      this.state = { infos: [], userId: '' }
  }

  componentWillMount() {
    this.getScoreFromAPI().then(data => {
      this.setState({ infos: data })
    });
    console.log(this.state.infos);
    AsyncStorage.getItem(USERID_STORED)
    .then((data) => {
        if (data) {
           this.setState({userId:data})
        }
    });
  }
  async getScoreFromAPI() {
      let formData = new FormData();
      formData.append('userId', this.state.userId);
      formData.append('key', '***'); //my key
    try {
      let response = await fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'multipart/form-data'
        },
        body: formData
      })
      let res = await response.json();

  } catch(error) {
      console.warn("errors are " + error);
  }
};

with a try-catch function but when I call getScoreFromAPI() in ComponentWillMount() I can't setState with received data, I still have an empty array in info:[] 使用try-catch函数,但是当我在ComponentWillMount()调用getScoreFromAPI() ,无法使用接收到的数据设置状态,信息中仍然有一个空数组:[]

my questions: 我的问题:

how can I replace '1' in userId by a value in asyncstorage in the first file ? 我如何用第一个文件中asyncstorage中的值替换userId中的'1'?

if it isn't possible, what I have do to setState info: [] with my data reveived 如果不可能的话,我对setState info:[]所做的操作已显示了数据

  1. You're doing your API call before fetching your value from AsyncStorage (I know this is async but it's not very readable if you do it that way). 在从AsyncStorage获取值之前,您正在执行API调用(我知道这是异步的,但是如果您这样做的话,它就不太可读)。
  2. getScoreFromAPI doesn't return anything, that's why your setState isn't working. getScoreFromAPI不返回任何内容,这就是为什么setState不起作用的原因。
  3. You don't need to use try and catch here, promises have their own error handling mechanism (the .catch() method). 您无需在此处使用try and catch ,promise具有自己的错误处理机制(.catch()方法)。
  4. I think callbacks are more readable and lead to less bugs than using .then() in code. 与代码中使用.then()相比.then()我认为回调更易读,并且导致的错误更少。

This is how I would do it: 这就是我要做的:

constructor(props)
{
    super(props);
    this.state = { infos: [], userId: '' };
    this.onSuccess = this.onSuccess.bind(this);
    this.onFailure = this.onFailure.bind(this);
}

componentWillMount()
{
    // Get userID from local storage, then call your API 
    AsyncStorage.getItem(YOUR_KEY)
        .then(userID=> {
            if (userID)
            {
                this.setState({ userId : userID }, () => {
                    this.getScoreFromAPI(this.onSuccess, this.onFailure); 
                });
            }
        });
}

onSuccess(data)
{
    this.setState({
        infos : data
    });
}

onFailure(err)
{
    console.warn('Error ' + err);
}

getScoreFromAPI(onSuccess, onFailure)
{
    let formData = new FormData();
    formData.append('userId', this.state.userId);
    formData.append('key', '***'); //your key

    fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
        method : 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'multipart/form-data'
        },
        body: formData
    })
    .then(res => res.json())
    .then(json => {
        onSuccess(json);
    })
    .catch(err => {
        onFailure(err);
    });
} 

I've simplified your code into a promise chain in which calling getScoreFromAPI will execute after getting the userId from AsyncStorage, then storing the response into the infos state, while returning null if there was an error, and logging the error to the console. 我已经将您的代码简化为一个getScoreFromAPI链,在该链中,从AsyncStorage获取userId之后将执行getScoreFromAPI调用,然后将响应存储到infos状态,同时在出现错误时返回null并将错误记录到控制台。 The data was not previously returned from getScoreFromAPI , so the value would always become null . 先前未从getScoreFromAPI返回数据,因此该值将始终为null I have not tested this code, but this should give you a good base to work from: 我尚未测试此代码,但这将为您提供一个良好的工作基础:

import FormData from 'FormData';
import AsyncStorage from '@react-native-community/async-storage';

export default class Test {
    constructor() {
        this.state = {
            infos: null,
            userId: ''
        };
    }

    componentDidMount() {
        AsyncStorage.getItem(this.state.userId)
            .then(userID => {
                this.setState({ userId: userID || '' });
            })
            .then(() => {
                return this.getScoreFromAPI();
            })
            .then(data => {
                this.setState({ infos: data });
            })
            .catch(console.error);
    }

    getScoreFromAPI = () => {
        const formData = new FormData();

        formData.append('userId', this.state.userId);
        formData.append('key', '***'); //my key

        fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
            method: 'POST',
            headers: {
                Accept: 'application/json',
                'Content-Type': 'multipart/form-data'
            },
            body: formData
        })
            .then(response => {
                // use response data here
                return response.json();
            })
            .catch(e => {
                console.error(e);
                return null;
            });
    };
}

It's finally done. 终于完成了 I tried this and it worked. 我尝试了一下,它起作用了。 Thank you to all of you 谢谢大家

this is what I have done: 这是我所做的:

...
const USERID_STORED = "userid_stored";
const GSM_STORED = "gsm_stored";
...
class ScoreList extends React.Component {
  constructor(props) {
      super(props)
      this.state = { infos: [], userId: '', gsmStored: '', }
  }

  componentWillMount() {
    AsyncStorage.getItem(USERID_STORED)
        .then(userId => {
                this.setState({ userId: userId});
                this.getScoreFromAPI(this.state.userId).then(data => {
                  this.setState({ infos: data });
                });
        });
    AsyncStorage.getItem(GSM_STORED)
        .then(gsmStore => {
                this.setState({ gsmStored: gsmStore});
        });
  }

  getScoreFromAPI (userId) {
    let formData = new FormData();
    formData.append('userId', userId);
    formData.append('key', '***');
    return fetch('https://***',{
                   method : 'POST',
                   headers : {
                     'Accept': 'application/json',
                     'Content-Type': 'multipart/form-data'
                   },
                   body : formData
               } )
         .then((response) => {
            return response.json()
         })
      .catch((error) => console.log("l'erreure est:  " + error))
   };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM