【问题标题】:React JS : Get data from api and send to child componentReact JS:从 api 获取数据并发送到子组件
【发布时间】:2018-02-09 10:03:32
【问题描述】:

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

你能解释一下我该怎么做吗? 这是我的代码的 sn-p:

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 请求,我想通过响应更改“用户”的状态,以便打印用户列表。但我不知道如何解决这个问题。

感谢您的帮助!

【问题讨论】:

  • GetData 超出范围。把它变成一个箭头函数,你应该没问题
  • 尝试将 GETDATA 方法放在类范围内

标签: javascript reactjs react-native react-router


【解决方案1】:

这里发生了一些事情。

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

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

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

您可以从componentDidMount() 执行此操作,因为组件已准备好,但如果您从该生命周期方法内部调用this.setState(),它将触发另一个重新渲染。有人称“setState inside componentDidMount”是一种反模式,但它并没有那么糟糕。我会说使用它,但请注意它确实会触发重新渲染。渲染方法将至少运行两次。如果您有一个大而复杂的组件或很多组件,则可能会导致性能问题。这就是为什么人们说“不要这样做”。

继续前进,我建议创建一个名为 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 请求,因为我使用它已经很长时间了。我无法验证您的语法是否正确。我建议使用名为requesthttps://www.npmjs.com/package/request 的库。我想 XHR 请求可以正常工作,但请查看请求作为学习练习。

【讨论】:

    【解决方案2】:

    this.setState 中的 this 上下文并不是您想象的那样。您可以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 代码。

    【讨论】:

      【解决方案3】:

      问题在于 this 的上下文,在 GetData 函数中它是未定义的,因此请尝试使用箭头函数为您的回调 () =&gt; {} 自动绑定来自 Utilisateurs 类的 this 上下文。

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

      【讨论】:

        【解决方案4】:

        你应该在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>
                );
            }
        }
        

        编辑: 实际上componentDidMount 是在React Docs 中推荐的,不幸的是,他们没有解释原因,但是一些关于 React 最佳实践的文章告诉我们,在第一次渲染之前获取可能会导致问题一些情况。

        【讨论】:

        • 可能有助于解释为什么
        • @Andy 你是对的,我编辑了我的帖子,但这实际上很难找到原因。
        猜你喜欢
        • 2020-09-28
        • 2019-09-07
        • 2019-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多