2017-03-02 44 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

相關問題