组件生命周期问题/无法处理未定义的

时间:2016-05-18 11:59:33

标签: javascript json react-native fetch

我正在创建一个应用程序,该应用程序应该在某个时刻获取带有标题,描述和用户信息的信息提要。我正在做反应本机,这也是同一视图中的两个独立的源,可以在两个选项卡之间切换,所以我认为我当前的架构随后将是最佳的。

手头的问题:

来自Methods.js:

exports.getFriendFeed = function(TOKEN) {
  return new Promise((resolve, reject) => {
      fetch(baseUrl + 'feed' , {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Token' : TOKEN,
      },
    })
    .then((response) => response.text())
    .then((responseText) => {

        resolve(responseText);
    })
    .catch((error) => {
        reject(error);
    });
  });
};

我写了获取请求并将其发送到我的home.js屏幕。并按如下方式处理:

var Home = React.createClass({
.
.
.
  changeComponent: function(component) {
    Method.getFriendFeed(this.state.tokenSupreme)
    .then((res) => this.setState({
      friendFeed: JSON.parse(res).friendPosts,
      loaded: true,
    }))
    .catch((error) => console.log(error))
    .done();     
    this.setState({
      componentSelected: component,
    })
  },

这意味着当我按下某个Feed视图时,内容会专门为该视图加载。

渲染组件并传递信息源的道具以及是否已加载:

  renderComponent: function(component) {
      if(component === 'One') {
        return <ComponentOne 
        friendData={
          this.state.friendFeed
        } 
        loaded={
          this.state.loaded
        } />
      } else if(component === 'Two') {
        return <ComponentTwo />
      }
  },

但现在出现了真正的问题。遵循React Native提供的文档。我有console.log'对rowData产生“加载”,然后它返回我想要的json格式数据。所以这意味着它首先成功通过changeComponent函数并变为“加载”,并错误地将this.state.loaded变为true,这意味着在此期间有一个时间点这个执行,我不能在我的json中调用任何特定的键或名称,因为它只加载了“种类”,它只是立即返回未定义和红色屏幕应用程序。

var ComponentOne = React.createClass({
  getInitialState: function() {
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
     return { 
      dataSource: ds.cloneWithRows(this.props.friendData),
   };
  },

  render: function() {
    if (!this.props.loaded) {
      return this.renderLoadingView(); 
    } else {
    return (
       <ListView 
          dataSource={this.state.dataSource} 
          renderRow={this.renderRow}
          style={styles.card} /> 
      )
    }
  },
   renderLoadingView: function() { 
    return ( 
      <View style={{alignItems: 'center', alignSelf: 'center', marginTop: 150, justifyContent: 'center'}} > 
        <Text style={{fontSize: 30, fontWeight: '400', color: '#666'}}> Loading ... </Text> 
      </View> 
      ); 
  },  

  renderRow: function(rowData) {
    return (
        <CardView
          name={rowData.name}
          fullname='xyz'
          distance='xyz'
          title={rowData.title}
          message={rowData.description} 
          score='xyz'
          stars='xyz'
          starcolors={colors.General.black}
          vouched="Example" />
      )
  }
})

为什么它给我这个?如果我把fetcher放在componentDidMount中,并且如果我将它放在渲染中,那么它永远不会真正激发。它会无限制地激发。

如何更有效地控制此执行/生命周期问题?我也尝试将其作为IF语句说if (this.props.friendFeed.friend.name !== undefined),但不管你信不信,它只是返回一个红色屏幕,上面写着this.props.friendFeed.friend.name is undefined。在密钥中调用对象可能是一个问题吗?我可以在定义之前调用这样的东西,而不是它被定义吗?

1 个答案:

答案 0 :(得分:0)

我看到两种可能的解决方案。首先,关于在未定义对象上调用键的最后一个问题。考虑这个对象......

{
  foo: {
    bar: 'text'
  }
}

如果在任何时候fooundefined,则无法检查子对象键是否也是undefined。您需要确定在加载数据时可能未定义的最高根对象。

因此,如果if (foo.bar !== undefined)foo,则此语句将失败:undefined。但是,这句话没问题:if (foo.hasOwnProperty('bar'))或技术上甚至是if (foo !== undefined)

至于你的主要问题,我的猜测是数据解析会发生异步事件。这就是我实现fetch ...

的方法
function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response.text().then((text) => {
      if (text == "") return ""
      return JSON.parse(text)
    })
    return response.json()
  }
}

get(id, query) {
  let url = this.API_URL() + '/' + id + this._generateQuery(query)
  return fetch(url, {
    method: 'get',
    headers: this._headers()
  }).then(this._checkStatus)
    .then((data) => {
      return data
    })

}

请注意我如何利用将正文处理成文本的承诺方面。我会尝试在changeComponent中执行类似的操作,以便它不会调用setState(并随后将加载设置为true),直到您确定数据已被解析为止。由于它是内联的,它可能会立即调用setState,然后在完成解析时短时间内呈现具有不完整数据的组件(因为它只是传递变量引用,而不是值)。