React Native 仅在第二次或第三次尝试时获取 returns

React Native fetch only returns on second or third attempt

我有一个使用使用 AsyncStorage 在本地保存的参数的提取。但是我在第二次或第三次尝试时只获取 returns 数据,所以当我尝试在我的渲染器上映射数据时,它说它无法映射未定义的数据。

这是我的 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})
    })
  }

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

您面临的问题是两种方法都是 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})
  })
}

已编辑:

看完整个组件后,结论是 render 方法在 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>
      );
    }
  }
}

上面的代码,我只留下了值得质疑的代码,原来的代码多了很多。