【问题标题】:Apollo + React: data not appearing in componentDidMount lifecycleApollo + React:数据未出现在 componentDidMount 生命周期中
【发布时间】:2018-06-17 16:58:34
【问题描述】:

我有一个 React 应用,它使用 Redux 进行一些应用内状态管理,并使用 Apollo 从服务器获取数据。在我的网络选项卡中,我的 graphql 查询成功并且响应是我所期望的,但是当我尝试在 React 组件的 componentDidMount 生命周期中引用数据时,数据不存在并且加载状态为“真”。

如果我将代码移动到不同的生命周期函数,例如 render(),数据确实会出现,但我需要它在 componentDidMount 中工作。我是阿波罗的新手。

import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";

import SdkMap from "@boundlessgeo/sdk/components/map";
import SdkZoomControl from "@boundlessgeo/sdk/components/map/zoom-control";

import * as mapActions from "@boundlessgeo/sdk/actions/map";

import { graphql } from "react-apollo";
import gql from "graphql-tag";

function mapStateToProps(state) {
  return {
    map: state.map
  };
}

class Map extends Component {
  static contextTypes = {
    store: PropTypes.object.isRequired
  };

  componentDidMount() {
    const store = this.context.store;
    store.dispatch(mapActions.setView([-95.7129, 37.0902], 3));

    /* ADD SITES LAYER */
    store.dispatch(
      mapActions.addSource("sites_src", {
        type: "geojson",
        data: {
          type: "FeatureCollection",
          features: []
        }
      })
    );

    store.dispatch(
      mapActions.addLayer({
        id: "sites",
        source: "sites_src",
        type: "circle",
        paint: {
          "circle-radius": 3,
          "circle-color": "blue",
          "circle-stroke-color": "white"
        }
      })
    );
    
    console.log(this.props.data);  //response doesn't include query fields
    if (this.props.data.allSites) {
      let sites = this.props.data.allSites.edges;

      for (let i = 0; i < sites.length; i++) {
        let site = sites[i].node;
        let geojson = site.geojson;
        if (geojson) {
          console.log(site);
          const feature = {
            type: "Feature",
            geometry: geojson,
            properties: {
              id: site.id
            }
          };
          store.dispatch(mapActions.addFeatures("sites_src", feature));
        }
      }
    }
  }

  render() {
    const store = this.context.store;

    return (
      <SdkMap store={store} >
        <SdkZoomControl />
      </SdkMap>
    );
  }
}

const query = graphql(
  gql`
    query {
      allSites {
        edges {
          node {
            id
            projectId
            location
            areaAcres
            geojson
          }
        }
      }
    }
  `
);

const MapWithRedux = connect(mapStateToProps)(Map);
const MapWithApollo = query(MapWithRedux);

export default MapWithApollo;

【问题讨论】:

    标签: reactjs apollo react-apollo


    【解决方案1】:

    首先不需要自己访问this.context。这是一种反模式。始终使用connect()。如果您需要组件中的部分状态,请使用mapStateToProps。如果您想从您的组件中调度操作,请使用mapDispatchToProps 将函数传递给它,为您执行调度。这是connect() 接受的第二个参数。

    此外,没有理由将 store 传递给子组件,因为您可以单独连接需要 store 中任何内容的每个组件。

    话虽如此,您的问题是获取数据是异步的,并且在调用 componentDidMount() 时您的请求可能未完成。所以loading 是真的信息只是意味着你的获取还没有完成。您可以通过例如向用户显示它显示某种微调器,或者在渲染组件之前获取所需的数据。

    【讨论】:

    • 谢谢,好的建议,我会做出这些改变。我只是遵循 Boundless SDK 的作者提供的 redux 模式,但看起来那里有一些改进。是的,显然异步获取在 componentDidMount() 被调用时还没有完成,但是如果我把从渲染方法中的 for 循环的东西,我得到一个无限循环的结果。
    • 把它放在render() 方法中不是解决方案。获取数据需要不确定的时间,具体取决于您无法始终影响的外部因素。您需要显示一些内容,表明您的组件仍在加载初始数据,只要它仍在获取。一旦数据到达,您的组件将使用数据重新渲染。或者您可以自己提供初始数据并将它们作为初始状态存储在您的 redux 存储中。
    • 还使用react-apollo 阅读prefetching 数据。这可能就是你想要的。
    • 感谢您尝试引导我完成此操作,但我仍然缺少一些东西。在 componentDidMount() 中,如果我使用 console.log(this.props.data.loading),我会得到“真”。尽管在那个生命周期方法中什么都不会再发生,那么我如何订阅才能知道它何时为“假”?
    • @bantingGamer 我对您的用例一无所知。在大多数情况下,您应该使用Query component 来获取数据,如果您熟悉 React 钩子,则应使用 useQuery。
    猜你喜欢
    • 2020-09-19
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    • 2017-03-09
    • 2019-01-02
    • 2017-01-06
    • 2021-12-12
    • 2018-06-22
    相关资源
    最近更新 更多