React JS:从api获取数据并发送到子组件

时间:2018-02-09 10:03:32

标签: javascript reactjs react-native react-router

我有点迷失了。我想从我的API获得响应并将数据发送到子组件。似乎我不明白该怎么做,因为它告诉我:" TypeError:无法读取属性' setState'未定义"

你能解释一下我该怎么办? 以下是我的代码片段:

function GetData(url, params, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url + '?' + params, true);
    xhr.onreadystatechange = function(e) {
        if (this.readyState === xhr.DONE) {
            if (this.status === 200) {
                callback(JSON.parse(xhr.responseText));
            } else {
                console.log('error');
           }
        }
    }
    xhr.send(null);
}

class Utilisateurs extends Component {
    constructor(props){
        super(props);
        this.state = {users:''}
        GetData('http://localhost:3333/shop/users', 'login=true', 
            function(res) {
               this.setState({users: res});
            }
        )

    }

    render() {
        return (
        <div id="center">             
            <UserListSorted data={this.state.users}></UserListSorted>
        </div>
        );
    }
}

所以我发出了一个GET请求,我想改变用户的状态&#39;有了响应,所以我可以打印一个用户列表。但我不知道如何解决这个问题。

感谢您的帮助!

4 个答案:

答案 0 :(得分:1)

this中的this.setState上下文不符合您的想法。你可以this重新分配给闭包之外的一个新变量,但是如果你使用箭头函数(它没有this并借用了上下文中的上下文,那就容易多了。外部范围)而不是:

GetData('http://localhost:3333/shop/users', 'login=true', (res) => {
  this.setState({ users: res });
});

除此之外:您可以在构造函数the React team recommend that you use componentDidMount中执行获取操作。有更多信息in this article

哦,您可以考虑使用fetch而不是编写所有XMLHTTPRequest代码。

答案 1 :(得分:1)

这里有几件事情。

首先,您不应该在constructorcomponentWillMount()中发出网络请求。有人可能会称它为反模式。

您不应该从constructor执行任何长时间运行的任务,因为它会使组件加载时间更长。这是一个很好的一般规则。只需使用它来设置变量和属性并触发其他类方法,快速设置。我无法记住,但它可能是同步与异步行为的问题。构造函数是一种方法。它是一个函数,因此如果您挂起线程等待网络请求,组件必须等待才能继续。

componentWillMount()也是如此。在将组件安装到DOM之前,该生命周期方法启动,这意味着如果您在安装组件之前发出网络请求并且完成,则没有任何setState。 DOM中还没有组件可用于setState。这是以前有人告诉我的事情,它一直困扰着我。我现在只是告诉你,希望能给你同样的实现时刻。

您可以从componentDidMount()执行此操作,因为该组件已准备就绪,但如果您从该生命周期方法内部调用this.setState(),则会触发另一次重新呈现。有些人在componentDidMount&#34;中调用&#34; setState反模式,但它并不是那么糟糕。我会说使用它,但请注意它确实会触发重新渲染。 render方法至少运行两次。如果你有一个庞大,复杂的组件或许多组件,它可能会导致性能问题。这就是为什么人们会说&#34;做不到的事情&#34;。

继续前进,我建议创建一个名为getData()的类方法,然后从componentDidMount()调用它。像这样:

class Something extends Component {
  constructor(props) {
    super(props)
    this.state = {
      data: '',
    }
  }

 componentDidMount() {
    this.getData()
  }

 getData() {
  // get data from server
  const theData = 'we got some data'
  this.setState({
    data: theData,
  })
 }

 render() {
   return <div>{this.state.data}</div>
 }
}

我实际上无法完全帮助您处理XHR请求,因为自从我使用XHR请求以来它一直都在使用它。我无法验证您的语法是否正确。我建议使用名为request https://www.npmjs.com/package/request的库。我想XHR请求可以正常工作,但请将请求作为学习练习。

答案 2 :(得分:0)

问题在于this的上下文,在GetData函数中它是未定义的,所以请尝试使用箭头函数进行回调() => {},它会自动绑定来自this类的Utilisateurs上下文

GetData(
  'http://localhost:3333/shop/users',
  'login=true', 
  res => {
    this.setState({users: res});
  }
)

答案 3 :(得分:0)

你应该在componentDidMount中进行api调用(除了使用箭头函数作为GetData()的回调):

class Utilisateurs extends Component {
    constructor(props){
        super(props);
        this.state = {users:''}
    }
    componentDidMount() {
        GetData('http://localhost:3333/shop/users', 'login=true', 
            (res) => {
               this.setState({users: res});
            }
        )
    }
    render() {
        return (
        <div id="center">             
            <UserListSorted data={this.state.users}></UserListSorted>
        </div>
        );
    }
}

修改React Docs实际上建议使用componentDidMount,但不幸的是,它们没有解释原因,但有些关于React最佳做法的文章告诉我们在第一次渲染之前提取在某些情况下会导致问题。