【问题标题】:React Native fetch only returns on second or third attemptReact Native fetch 仅在第二次或第三次尝试时返回
【发布时间】:2017-10-24 23:58:01
【问题描述】:

我有一个使用 AsyncStorage 在本地保存的参数的 fetch。但是我的 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})
    })
  }

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

【问题讨论】:

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


    【解决方案1】:

    您面临的问题是两种方法都是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 之前和之后执行了一次,这就是为什么第一次是 undefined,第二次是你期望的值。

    因此,为了解决这种情况,一种可能的方法是标记获取数据的操作并在获取完成后进行渲染。或多或少,这个想法是:

    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>
          );
        }
      }
    }
    

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

    【讨论】:

    • 感谢您的回答!不幸的是,它没有用。打印this.state.value确实正确打印了数字。但是当它尝试获取数据时,它会尝试 2 或 3 次。
    • 好的,但是我们有一些更复杂的情况。 componentWillMount 执行了多少次? AsyncStorage.getItem 的结果是什么?它不应该尝试不止一次,所以如果它被执行了不止一次,也许我们在某个地方有某种循环。如果在componentWillMount 开头添加一个console.log,该日志会看到多少次?
    • componentWillMount 只执行了 1 次,而AsyncStorage 返回了一个汽车 ID,在这种情况下它返回了这个号码 437615
    • 那么,您在fetch 之前看到的值是多少?
    • 在获取 undefined 之前,就像在我共享的打印屏幕上一样。你问的是这个吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多