美文网首页react nativeReact Native开发
React native fetch获取JSON问题

React native fetch获取JSON问题

作者: 回调的幸福时光 | 来源:发表于2016-04-26 18:00 被阅读7256次
    //组件渲染完毕时调用此方法
    componentDidMount(){
       //get方法,只填写url参数
        fetch('http://192.168.71.150:3000/json/commondity.json')
           //上面一行会返回响应对象,即response
          .then((response)=>response.json())
          //response.json()将返回一个json类型对象
          .then((json)=>{
            this.setState({source:json});
          //注意我们在Promise调用链的最后调用了done() —— 这样可以抛出异常而不是简单忽略。
          }).done();
      }
    
    以上then()方法是promise调用链中的回调方法

    在此发现一个坑!

    constructor(props){
        super(props);
        this.state={
            source:{},
            single:0,
        };
      }
    

    在上面的fetch回调方法中,我们将从服务端获取的数据以json对象类型放到state中的source变量中,问题就出在这里!如果我们要从source中获取数据,用如下语句this.state.source[0].id来获取id值会报错。(此处json数据为数组)

    原因:

       source:{},    
    

    由于初始赋值为{},而在setState()之前就用到this.state.source[0].id,此时source不是数组,也没有id这个字段,{}只是undefined

    注:setState语句在componentDidMount()时才执行,而this.state.source[0].id在componentWillMount()时就执行

    解决方案:

    source赋值为初始调用语句的对应结构

    接着第二个问题

    JSX语法之谜

    错误写法
    return(
      <View style={styles.container}>
      {    var list = [];
          for (var i in this.state.source){
            var Row = (
              <Text key={i}>{this.state.source[i].title}</Text>
            )
            list.push(Row);
          }
      }
      {list}
    </View>
    )
    

    以上写法严重错误,{}中应该是属性表达式,更直观的说应该是已经定义好的变量。{}中可以使用条件表达式(?:)

    上述第一个{}中的for in部分可以写在render中,切记不可在return中!!!

    相关文章

      网友评论

      • 96dd91ad9a8f:是这样的,setTimeout将延迟时间设为0 ,这样,,setTimeout里的函数会先render执行,我还不清楚为什么,估计是只是context导致的
        96dd91ad9a8f:所以第一次执行到render的时候,state中的_data是[].第二次_data才有数据,所以才有了,空白到有数据的过程,我的理解是这样哈
        96dd91ad9a8f:是呀,正常应该先WillMount 在render。但是WillMount里面不是有fetch么,他是异步的,他执行到fetch时,就会render,同事,fetch也会执行,当fetch执行到setState的时候,又会再一次render,应该是这样,,
        回调的幸福时光: @D_lance 我知道settimeout涉及到异步请求,是先注册,然后在回调函数中执行fetch。把settimeout放在WillMount里面?这样当执行到settimeout时按道理只是注册一下就向下继续运行,就是render,但是你设置为0,所以立刻就执行回调里面的fetch,直到加载完数据才会执行render。而如果你不写settimeout,不也应该是执行完fetch再去render的吗?为什么render会在fetch之前?
      • 96dd91ad9a8f:恩,是呀,就是还没想到一个好的解决方案,其实放在setTimeout里的话,就会先于render执行,但是将fetch放在setTimeout 感觉很奇怪
        回调的幸福时光: @D_lance settimeout类似于延迟,应该延迟render吧,把fetch放在settimeout里面不是延迟fetch吗???
      • 96dd91ad9a8f:我其实也试过,跟下代码,其实还是会先进render,然后再进fetch里面,然后在render,
        回调的幸福时光:@D_lance 这就不知道怎么弄了,加载数据再快也需要时间,除非render之前,数据已经加载完毕
      • 96dd91ad9a8f:不是呀,就三条数据,,其实问题始终是像你这篇帖子说的一样,第一次render的时候,_data=[],当执行到componentDidMount()的时候,fetch到数据,通过setState再次出发render,造成了现在的由空白到有数据的一个突变
        回调的幸福时光: @D_lance 那更简单啦,你不要在componentDidMount里去请求数据,而是在componentWillMount里面去请求数据
      • 96dd91ad9a8f:用了listview 但是仍然有,一下从空白到有数据的一个突变,和用map渲染并没有区别
        回调的幸福时光: @D_lance 是因为数据太多吗?listview里面可以设置initialListSize
      • 96dd91ad9a8f:就是将fetch回来的 数据存在state一个属性中,如:_data:[] 这个空数组中,,let arrangeList = _data.map((item,i)=>{// 处理 item} 然后将 arrangeList放在render里,,你能明白么
        回调的幸福时光: @D_lance 明白,我以前也这样,为什么不用listview
      • 96dd91ad9a8f:哦,你是这个意思哟,我现在遇到一个类似的问题,就是渲染fetch获取的数据,这样会导致,页面是先出现空白,后出现数据,我只能用ActivityIndicatorIOS 来显示个加载中的状态,你有更好的解决方案么
        回调的幸福时光: @D_lance你用什么渲染的?
      • 96dd91ad9a8f:这个我明白,我不明白的是,你说的解决方案是什么意思,就是什么是“初始调用语句的对应结构”
        回调的幸福时光: @D_lance 就是state里面的初始赋值的source需要和你第一次调用的语句中的source保持一致,两边应该对应
      • 96dd91ad9a8f:source赋值为初始调用语句的对应结构?这个是什么意思
        回调的幸福时光:@D_lance 你调用的语句是this.state.source[0].id,那么这个语句中的source代表的是一个数组,并且这个数组的下标为0的元素应该有值,所以你在state中给source初始赋值时,应该给他赋一个数组,并且保证这个数组第一个元素存在,都在当你调用那个语句时,会报如下这样的错---这个元素为undefined--- 你看懂了吗?

      本文标题:React native fetch获取JSON问题

      本文链接:https://www.haomeiwen.com/subject/sqaqrttx.html