使用 Apollo Client 动态设置 React 组件的 GraphQL 查询 [英] Dynamically set GraphQL queries for React components with Apollo Client
问题描述
我正在构建一个 React 前端,它允许用户从静态查询列表中选择一个活动"查询,并将结果展平到表格中.将 GraphQL 查询从高阶组件传递到嵌套子组件的最佳方法是什么?
我见过的大多数文档/解决方案都侧重于将静态查询与从组件状态的动态条件绑定到组件,这不符合我的目的,因为不同的静态查询具有不同的字段并查询不同的节点类型.
这里的最佳实践/推荐方法是什么?我觉得这不是一个非常独特的用例,但我似乎找不到任何可以做类似事情的例子.
我使用 Apollo-Client/Redux 作为我的客户端存储.
以下是组件的大致轮廓:
class GridViewPage extends React.Component{构造函数(道具,上下文){超级(道具,上下文);this.state = {activeQuery = ... 存储选定的查询 ...};}使成为() {返回 (<div className="gridContainer">...此处的组件允许用户从活动列表中选择一个查询并将其/它的 ID/索引保存到状态...<面板可折叠>...一些工具栏组件...</面板>...此处的组件显示查询的结果(理想情况下通过接收查询或作为道具的结果?)...
);}}GridViewPage.propTypes = {网格:PropTypes.array.isRequired,动作:PropTypes.object.isRequired};函数 mapStateToProps(state, ownProps) {返回 {//接收可用查询列表作为道具网格:state.grids};}
我们以下面的组件为例:
ProfileWithData.js
import React, { Component, PropTypes } from 'react';从'react-apollo'导入{graphql};从'graphql-tag'导入gql;类配置文件扩展组件 { ... }Profile.propTypes = {数据:PropTypes.shape({加载:PropTypes.bool.isRequired,当前用户:PropTypes.object,}).是必须的,};//我们使用 gql 标签将我们的查询字符串解析为查询文档const CurrentUserForLayout = gql`查询 CurrentUserForLayout {当前用户 {登录头像网址}}`;const ProfileWithData = graphql(CurrentUserForLayout)(Profile);
使用高阶组件:
Profile.js
import React, { Component, PropTypes } from 'react';导出类配置文件扩展组件 { ... }Profile.propTypes = {数据:PropTypes.shape({加载:PropTypes.bool.isRequired,当前用户:PropTypes.object,}).是必须的,};
createProfileWithData.js
import React, { Component, PropTypes } from 'react';从'react-apollo'导入{graphql};从./配置文件"导入{配置文件}导出默认函数 createProfileWithData(query) =>{返回graphql(查询)(配置文件);}
然后你会像这样使用它:
Page.js
import React, { Component, PropTypes } from 'react';从'graphql-tag'导入gql;从 './createProfileWithData' 导入 createProfileWithData;类页面扩展组件{renderProfileWithData() {const { textQuery } = this.props;//最简单的方法,尽管您也可以将 gql 作为函数调用const graphQLQuery = gql`${textQuery}`;const profileWithDataType = createProfileWithData(graphQLQuery);返回 (<profileWithDataType/>);}使成为() {返回 (<div>..{this.renderProfileWithData()}..</div>)}}Profile.propTypes = {textQuery: PropTypes.string.isRequired,};
我想你明白了.
当然,您的 Profile 不会收到 props.data.currentUser
,而是 props.data.*
取决于根查询,您将处理视内容而定.
注意:这是直接在 Stack Overflow 中编写的,所以如果您遇到任何问题 - lmk,我会修复它.
I'm building a React front end which allows users to select an "active" query from a list of static queries and flattens to the result to be displayed in a table. What is the best way to pass the GraphQL query from a higher-order component into a nested child component?
Most of the documentation/solutions that I've seen focus on binding a static query with dynamical conditions from component states to a component, which would not work for my purpose as the different static queries have varying fields and query different node types.
What is the best-practice/recommended approach here? I feel like this is not a very unique use case, but I can't seem to find any examples that would do something similar.
I'm using Apollo-Client/Redux as my client-side store.
Below is the rough outline of the component:
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
};
}
Let's take, for example, the following component:
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);
It would be quite easily wrapping it with a 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);
}
You would then use it like this:
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,
};
I think you get the point.
Of course, your Profile would not received props.data.currentUser
, rather it would be props.data.*
depending on the root queries, and you would handle it appropriately depending on the contents.
Note: this was written directly in Stack Overflow, so if you encounter any problems - lmk and I'll fix it.
这篇关于使用 Apollo Client 动态设置 React 组件的 GraphQL 查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!