React Native - 用于获取响应的setState(不设置并停止执行代码)

时间:2018-03-05 11:36:47

标签: react-native

我正在尝试将App组件中的users: []设置为fetch的响应。

当我尝试使用this.setState更改users:的值时,我的代码停止执行,this.state.users仍为空。

不太清楚最新情况,我是否错误地使用componentWillMount? (有人在教程中使用它,我对生命周期方法的正确使用感到有些困惑)

我是这个React malarky的新手。

此外,由于' Expo'没有回应我像疯子一样摇动我的手机,我无法查看错误日志。

import React, {Component} from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default class App extends React.Component {

  constructor() {
    super();

    this.state = {
      users: [],
    }
  }

  componentWillMount() {
    // Not sure if I'm using this ^ correctly
    this._fetchUsers();
  }

  render() {
    const users = this._getUsers();
    return (
      <View style={styles.container}>
        <Text>Users</Text>
        <View>
          {users}
        </View>
      </View>
    );
  }

  _fetchUsers() {
     fetch('http://api.example.111.111.11.111.xip.io/users')
     // This ^ is returning json
     .then((response) => {
       console.log(1)
       // This ^ log is visible 
       this.setState({users: response._bodyText});
       // Code stops executing around here
       console.log(2)
       // This ^ log is not visible
     })
   }

  _getUsers() {
    return this.state.users.map((user) => {
        return(<User
                name={user.name}
                email={user.email}
                key={user.id} />);
    })
  }
}

class User extends React.Component {
  render() {
    return(
      <View className="user">
        <Text className="user-name">{this.props.name}</Text>
        <Text className="user-email">{this.props.email}</Text>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  }
});

response._bodyText返回与此类似的用户对象数组: [{id:'1', name:'Steve', email:'steve@example.com'},{id:'2', name:'notSteve', email:'notsteve@example.co.uk'.... ect

非常感谢任何帮助。

由于

更新:目前正在重新下载xcode以使应用程序在模拟器上运行,使用expo应用程序时遇到很多问题,即使在保存更改后重建相同的代码,也必须继续重新安装应用程序以运行更改,甚至仍然有问题。应该在45分钟到一个小时内进行另一次更新,感谢目前为止的所有答案。感觉就像我在学习东西 :d

最新更新:好的,问题已经解决,但尚未完全理解。

我的response看起来像这样:

Response {
13:43:00:   "_bodyInit": "[{\"id\":2,\"name\":\"Joe Bloggs\",\"email\":\"joe@example.com\", ........ect]",
13:43:00:   "_bodyText": "[{\"id\":2,\"name\":\"Joe Bloggs\",\"email\":\"joe@example.com\", ........ect]
13:43:00:   "headers": Headers {
13:43:00:     "map": Object { ........... ect

所以使用response._bodyText给了我一串json,这解释了为什么它不作为一个对象。

正如@Srdjan Cosic所建议的

response.json()给了我:

Promise {
13:54:17:   "_40": 0,
13:54:17:   "_55": null,
13:54:17:   "_65": 0,
13:54:17:   "_72": null,
13:54:17: }

我还没有承诺承诺,所以根本没有理解这一点。

response.data给了我undefined

最后,@ {srdjan Cosic再次提出了部分建议的工作this.setState({users: JSON.parse(response._bodyText)})

奇怪的是,this.setState({users: JSON.parse(response)})返回了完全相同的内容,但仍然无效:/

TL; DR - 我已经开始使用componentDidMount(thanks for the advise everyone),我的回复json很奇怪,所以必须使用this.setState({users: JSON.parse(response._bodyText)})将部分json转换为对象。

感谢大家的帮助。

3 个答案:

答案 0 :(得分:0)

永远不要在componentWillMount()中使用副作用(如api调用,获取数据或setState等异步调用),就像在首次呈现或装载组件之前一样。在呈现发生之前,不会返回对获取数据的异步调用。因此将this._fetchUsers()放在componentDidMount()。

让我知道它是否有效)

答案 1 :(得分:0)

首先,根据关于componentWillMount() https://reactjs.org/docs/react-component.html#componentwillmount的Reacts文档 它说

  在安装发生之前调用

componentWillMount()。它在render()之前调用,因此在此方法中同步调用setState()不会触发额外的渲染。通常,我们建议改为使用constructor()

     

避免在此方法中引入任何副作用或订阅。对于这些用例,请改用componentDidMount()

这基本上意味着您应该尝试在._fetchUsers()constructor()中呼叫componentDidMount()

第二件事,我不确定response._bodyText是什么,因为我在Fetch上的文档中找不到任何关于它的内容但是如果响应对象是fetch文档中描述的那个,那么你有权访问.body属性。所以不要这样做 this.setState({users: response._bodyText})为什么不尝试this.setState({users: JSON.parse(response.body)})这将解析正文(假设它是你所描述的json格式)并将其转换为javascript对象。

我使用axios,如果我的响应返回一个json,我通常可以使用response.data访问它,这样也可以用于获取。否则,response.json()还会在响应变为json https://developer.mozilla.org/en-US/docs/Web/API/Body/json之后返回另一个承诺

答案 2 :(得分:0)

在使用之前,您必须将response强制转换为json

 async _fetchUsers() {
   let response = await fetch('http://api.example.111.111.11.111.xip.io/users');
   let responseJson = await response.json();
   return responseJson.movies;
  })
 }

componentWillMount() {
  let users = this._fetchUsers();
  this.setState({ users });
}