React Native fetch仅在第二次或第三次尝试时返回

时间:2017-05-24 14:46:07

标签: javascript react-native fetch async.js asyncstorage

我有一个使用AsyncStorage本地保存的参数的提取。但是我的fetch仅在第二次或第三次尝试时返回数据,因此当我尝试在我的渲染上映射数据时,它表示它无法映射未定义的数据。

这是我的AsyncStorage和获取代码:

  componentWillMount(){
    AsyncStorage.getItem('key').then((codigo)=>{
      this.setState({value: JSON.parse(codigo)});
      this.getData()
    })
  }


  getData(){
    fetch(`URL/portalacv_ws.asmx/GetDetalhesViatura?CarID=${this.state.value}`)
    .then((response) => { return response.json()})
    .then(res => {
       this.setState({data: res})
    })
  }

这是我在控制台上获得的:

enter image description here

1 个答案:

答案 0 :(得分:2)

您遇到的问题是两种方法都是async。在您的情况下,您应该在获得项目后拨打getData作为回电。

您的代码说明:

componentWillMount(){
  AsyncStorage.getItem('key').then((codigo)=>{
    //This code runs async, so when you call getData, value has not been changed yet (Or at least you cannot be sure).
    this.setState({value: JSON.parse(codigo)});
    //Printing here this.state.value will help you to understand
    this.getData()
  })
}

getData(){
  fetch(`URL/portalacv_ws.asmx/GetDetalhesViatura?CarID=${this.state.value}`)
  .then((response) => { return response.json()})
  .then(res => {
     this.setState({data: res})
  })
}

如何解决?:

componentWillMount(){
  AsyncStorage.getItem('key').then((codigo)=>{
    this.setState({value: JSON.parse(codigo)}, () => {
        //Here you are pretty sure that the setState has already done.
        this.getData()
    });
  })
}

getData(){
  fetch(`URL/portalacv_ws.asmx/GetDetalhesViatura?CarID=${this.state.value}`)
  .then((response) => { return response.json()})
  .then(res => {
     this.setState({data: res})
  })
}

EDITED:

在看完整个组件后,结论是渲染方法在setState之前执行一次,之后执行一次,这就是为什么你第一次没有定义,第二次是你期望的值。

因此,为了解决这种情况,一种可能的方法是在获取完成后通过扩展获取数据和呈现的操作。或多或少,这个想法将是:

export default class Favoritos extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
      data: null,
      fetching: false
    };

    //Binding is not needed, but...
    this.getData = this.getData.bind(this);
    this.onPress = this.onPress.bind(this);
  }

  componentWillMount(){
    this.setState({ fetching: true }, () => {
      AsyncStorage.getItem('key').then((codigo)=>{
        this.setState({value: JSON.parse(codigo)}, () => {
          this.getData()
            .then((data) => {
              this.setState({
                data: data,
                fetching: false
              })
            })
        });
      })
    });
  }


  getData(){
    return fetch(`URL/portalacv_ws.asmx/GetDetalhesViatura?CarID=${this.state.value}`)
             .then((response) => { return response.json()})
  }

  onPress(){
    this.setState({ fetching: true }, () => {
      this.getData()
        .then((data) => {
          this.setState({
            data: data,
            fetching: false
          })
        })
    });
  }   

  render() {
    if(this.state.fethcing){
      return (
        <View style={{ flex: 1, backgroundColor: 'white' }}>
          Fetching data...
        </View>
      );
    } else {
      return (
        <View style={{ flex: 1, backgroundColor: 'white' }}>
          <ScrollView>
            <TouchableHighlight onPress={this.onPress}>
              ...
            </TouchableHighlight>
            <Text>
              {this.state.value}
            </Text>
          </ScrollView>
        </View>
      );
    }
  }
}

在上面的代码中,我只留下了有意义的代码,原始代码有更多的代码。