2017-03-02 67 views
5

我正在构建一个React前端,它允许用户从静态查询列表中选择“活动”查询并将其平滑到要在表中显示的结果。将GraphQL查询从高阶组件传递到嵌套子组件的最佳方法是什么?动态地为Apollo客户端设置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 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 
 
    }; 
 
}

回答

2

让我们,例如,下列各项组件:

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.*,您可以根据内容适当地处理它。

注意:这是直接写在堆栈溢出,所以如果你遇到任何问题 - lmk和我会解决它。

+0

谢谢!已经开始在项目中应用这种模式,并且我认为我将最终实现它。我遇到的一个即时错误是'const profileWithDataType = createProfileWithData(graphQLQuery);' 返回一个函数类型,因此嵌套在{{this.renderProfileWithData()}'内时不会触及'render()'函数? 这可能是我的代码的语法问题,但值得一提。 – Mike

+0

是的,这可能是JSX的一个问题。我总是会忘记这个语法是否有效。你也可以这样做: ''' return React.createElement(profileWithDataType,{}); ''' 我确定你已经解决了这个问题,所以更新会很好:) – advance512

+0

嘿!实际上,我最终跳过了createProfileWithData.js并将查询设置为直接在Page.js中的页面,与'graphql(query)(Profile)'等效,它的工作原理是:) – Mike

相关问题