【问题标题】:Dynamically set GraphQL queries for React components with Apollo Client使用 Apollo Client 为 React 组件动态设置 GraphQL 查询
【发布时间】:2017-07-21 20:09:56
【问题描述】:

我正在构建一个 React 前端,它允许用户从静态查询列表中选择一个“活动”查询,并将结果展平为要在表格中显示的结果。将 GraphQL 查询从高阶组件传递到嵌套子组件的最佳方法是什么?

我看到的大多数文档/解决方案都侧重于将静态查询与从组件状态到组件的动态条件绑定,这不适用于我的目的,因为不同的静态查询具有不同的字段并查询不同的节点类型.

这里的最佳实践/推荐方法是什么?我觉得这不是一个非常独特的用例,但我似乎找不到任何可以做类似事情的例子。

我使用 Apollo-Client/Redux 作为我的客户端存储。

下面是组件的大致轮廓:

class GridViewPage extends React.Component{
  constructor(props, context) {
    super(props, context);
    this.state = {
      activeQuery = ... Stores the selected query ...
    };
  }

  render() {
    return (
      <div className="gridContainer">
        ...Component here allows users to select a query from the active list and saves it/it's ID/Index to the state...

        <Panel collapsible>
        ...Some toolbar components...
        </Panel>
        ...Component here displays the result of the query (Ideally by receiving the query or the result of as a prop?)...
      </div>
    );
  }
}

GridViewPage.propTypes = {
  grids: PropTypes.array.isRequired,
  actions: PropTypes.object.isRequired
};

function mapStateToProps(state, ownProps) {
  return {
      // Receives list of available queries as a prop
      grids: state.grids
  };
}

【问题讨论】:

    标签: reactjs react-redux graphql react-apollo


    【解决方案1】:

    我们以下面的组件为例:

    ProfileWithData.js

    import React, { Component, PropTypes } from 'react';
    import { graphql } from 'react-apollo';
    import gql from 'graphql-tag';
    
    class Profile extends Component { ... }
    Profile.propTypes = {
      data: PropTypes.shape({
        loading: PropTypes.bool.isRequired,
        currentUser: PropTypes.object,
      }).isRequired,
    };
    
    // We use the gql tag to parse our query string into a query document
    const CurrentUserForLayout = gql`
      query CurrentUserForLayout {
        currentUser {
          login
          avatar_url
        }
      }
    `;
    
    const ProfileWithData = graphql(CurrentUserForLayout)(Profile);
    

    higher order component 包装它会很容易:

    Profile.js

    import React, { Component, PropTypes } from 'react';
    
    export class Profile extends Component { ... }
    Profile.propTypes = {
      data: PropTypes.shape({
        loading: PropTypes.bool.isRequired,
        currentUser: PropTypes.object,
      }).isRequired,
    };
    

    createProfileWithData.js

    import React, { Component, PropTypes } from 'react';
    import { graphql } from 'react-apollo';
    import { Profile } from './Profile'
    
    export default function createProfileWithData(query) => {
      return graphql(query)(Profile);
    }
    

    然后你会像这样使用它:

    Page.js

    import React, { Component, PropTypes } from 'react';
    import gql from 'graphql-tag';
    import createProfileWithData from './createProfileWithData';
    
    class Page extends Component {  
    
      renderProfileWithData() {
    
          const { textQuery } = this.props;
          // Simplest way, though you can call gql as a function too
          const graphQLQuery = gql`${textQuery}`;
    
          const profileWithDataType = createProfileWithData(graphQLQuery);
    
          return (
            <profileWithDataType />
          );
      }
    
      render() {
    
        return (<div>
                    ..
                    {this.renderProfileWithData()}
                    ..
               </div>)
      }
    
    }
    
    Profile.propTypes = {
      textQuery: PropTypes.string.isRequired,
    };
    

    我想你明白了。

    当然,您的个人资料不会收到props.data.currentUser,而是props.data.*,具体取决于根查询,您将根据内容进行适当处理。

    注意:这是直接在 Stack Overflow 中编写的,所以如果您遇到任何问题 - lmk,我会修复它。

    【讨论】:

    • 谢谢!已经开始在项目中应用这种模式,我想我最终会让它发挥作用。我遇到的一个直接错误是const profileWithDataType = createProfileWithData(graphQLQuery); 正在返回一个函数类型,因此当嵌套在{this.renderProfileWithData()} 中时没有命中render()function?这可能是我的代码的语法问题,但值得一提。
    • 是的,这可能是 JSX 的问题。我总是忘记该语法是否有效。你也可以这样做:``` return React.createElement(profileWithDataType, {}); ```我确定你现在已经解决了这个问题,所以更新会很好:)
    • 嘿!实际上我最终跳过了 createProfileWithData.js 并直接在 Page.js 中将查询设置为页面,相当于graphql(query)(Profile) 并且它有效:)
    猜你喜欢
    • 2017-12-02
    • 2018-02-10
    • 2019-01-07
    • 2022-08-17
    • 1970-01-01
    • 2017-03-10
    • 2019-03-13
    • 2018-11-06
    • 2016-11-30
    相关资源
    最近更新 更多