【问题标题】:correct way to call api using react使用 react 调用 api 的正确方法
【发布时间】:2018-04-29 03:43:06
【问题描述】:

我有一个如下的反应代码,它基本上创建了一个树形图:

class ChartModal extends Component{
   constructor(props){
      super(props)
}
callApi(){

  fetch(someurl)
  .then((result) => {

    return result.json();
  }).then((jsonResult) => {
    console.log(jsonResult);
  })
}
render(){
  return(
    <Modal
            onOk={() => this.props.toggleVisibility()}
            onCancel={() => this.props.toggleVisibility()}
            visible={this.props.isVisible}
            okText={'ok'}
            cancelText={'cancel'}
            confirmLoading={false}
            title="Intent distribution chart"
        >
            <h1>HOWDY</h1>
            <TreeMap
                data =  {this.callApi()}//this is where i want the data returned by apicall
                width={400}
                valueUnit={'count'}
            />
        </Modal>
    )
  }
}

现在我希望 api 调用返回的数据在 tree map 组件中使用,但我现在这样做的方式似乎不起作用。 当我运行它时,tree map 中的数据为空,尽管我希望api call 返回的json 存在。

【问题讨论】:

  • 你的意思是它不工作?请更具体。它会抛出错误吗?如果是这样,什么错误?给出不希望的结果?期望的结果是什么?这会返回什么?
  • @Antimony 当我运行它时,treemap 中的数据为空。

标签: javascript reactjs d3.js react-native


【解决方案1】:

您需要在componentWillMount 或任何其他生命周期挂钩中调用API,并在您的API 回调中使用setState 以确保将结果设置为组件状态变量。这样,在setState 之后,您的组件就可以访问由您的 API 调用解析的值。

注意:this.state.result 在第一次渲染期间将为空。确保在访问 this.props.data 之前对 TreeMap 组件进行空检查。

小提示

来自 @aram90 关于在未安装组件上调用 setState 的好建议。为了避免这种this.canSetState,我定义并添加了实例变量以防止在未安装的组件上调用任何可能的setState

我使用这种方法只是为了尽早调用 API,即使这意味着一纳秒。但是,另一种方法是调用componentDidMount 中的API,然后相应地检查this._ismounted 实例变量。有关此结帐的更多信息,请点击此处Is there a way to check if the react component is unmounted? 的答案。 React 文档建议不要使用isMounted()

有很多方法可以实现这一点,但这是更多的 React 方式。

class ChartModal extends Component{
  constructor(props){
    super(props)

    this.state = {
      result: null
    }
    this.canSetState = false;
  }

  componentWillMount() {
    this.canSetState = true;
    this.callApi();
  }

  componentWillUnmount() {
    this.canSetState = false;
  }

  callApi(){

    fetch(someurl)
    .then((result) => {

      return result.json();
    }).then((jsonResult) => {
      this.canSetState && this.setState({result: jsonResult})
    })
  }

  render(){
    return (
      <Modal
        onOk={() => this.props.toggleVisibility()}
        onCancel={() => this.props.toggleVisibility()}
        visible={this.props.isVisible}
        okText={'ok'}
        cancelText={'cancel'}
        confirmLoading={false}
        title="Intent distribution chart"
      >
        <h1>HOWDY</h1>
        <TreeMap
          data={this.state.result}
          width={400}
          valueUnit={'count'}
        />
      </Modal>
    )
  }
}

【讨论】:

  • 实际上这种方法可能会在组件卸载后完成获取 URL 时导致错误。 React 在尝试在未安装的组件上调用 setState 时会抛出错误。修复它的一种简单方法是在异步功能之后设置状态之前检查组件是否仍然安装。而且最好从componentDidMount 调用API,这样如果在组件实际挂载之前调用返回太快,isMounted 检查就不会失败。
  • 这实际上是一个很好的收获。 @aram90 您能否检查一下这是否相似。我只是更喜欢尽早发出 API 调用。让我知道这是否也能奏效?
  • Kalindindi 你的方法也很好,即使在安装组件之前检查是没有必要的,因为你甚至可以在安装之前设置状态。但是,React 文档说:“componentDidMount() 在组件安装后立即调用。需要 DOM 节点的初始化应该在这里。如果您需要从远程端点加载数据,这是实例化网络请求的好地方。 " reactjs.org/docs/react-component.html#componentdidmount
【解决方案2】:

问题是 callApi 没有返回任何东西。如果它应该在某处分配数据,它不是。如果确实返回了一些东西,那将是一个承诺,因为它是异步的。

您可以做的是使用状态变量并将其映射到您的TreeMapdata 属性。然后使用 componentDidMount 生命周期函数在组件渲染后获取数据。一旦它响应,用结果更新映射的状态变量。理论上,它应该自动重新渲染TreeMap

【讨论】:

    猜你喜欢
    • 2017-02-26
    • 2019-12-13
    • 2017-09-04
    • 2016-12-09
    • 1970-01-01
    • 2016-10-12
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多