[英]Is there a way to pass a dynamic GraphQL query to a graphql() decorated Component when using Apollo Client 2.0?
使用动态数据时,有时会遇到此问题。 对于在需要的数据可用之前已安装的高阶组件来说,这是一个问题。
我正在Apollo Client中使用graphql()
HOC装饰组件,如下所示:
export default compose(
connect(),
graphql(QUERY_NAME), <-- I want QUERY_NAME to be determined at run-time
)(List)
问题是我不知道如何在运行时让Apollo使用由包装的组件确定的查询 。
我有一个根据类型导出查询的文件:
import listFoo from './foo'
import listBar from './bar'
import listBaz from './baz'
export default {
foo,
bar,
baz,
}
我可以通过listQueries[type]
访问它们,但是type
仅在组件内部是已知的,并且可以作为this.props.fromRouter.type
。
有没有我可以用来实现的策略:
export default compose(
connect(),
graphql(listQueries[type]),
)(List)
我认为可能有这样一种方法:
export default compose(
connect(),
graphql((props) => ({
query: listQueries[props.fromRouter.type],
})),
)(List)
我在正确的轨道上吗?
另一个可能的解决方案是使Component生成自己的子组件,该子组件用graphql()
包装,因为graphql()
查询将为人所知。
例如:
const tableWithQuery = graphql(listQueries[props.fromRouter.type])((props) => {
return <Table list={props.data} />
})
我想我知道了。
我有一个读取this.props.match.params
的路由器组件,以获取视图类型和请求的操作 。
利用这些信息,我只能创建一个List,Create,Edit和View Component,并为每个组件提供所需的查询。
我创建了一个函数,该函数可以获取所提供类型的所有查询和变异。
实际上,仅使用诸如<List />
类的组件并用graphql()
对其进行包装,并graphql()
提供刚刚确定的正确查询或突变是非常简单的。
现在,使用正确的数据填充this.props.data
来安装组件
我散布了所有查询和变异,以防万一我需要它们。 我怀疑当我阅读this.props.data[listQueryName]
时会需要它们。 (它将在例如this.props.data.getAllPeople
获取数据)
这是逻辑(我将包括所有内容,以最大程度地减少将来搜索者的困惑):
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose, graphql, withApollo } from 'react-apollo'
import listQueries from './list/queries'
import createMutations from './forms/create/mutations'
import editMutations from './forms/edit/mutations'
import viewQueries from './forms/view/queries'
import List from './list/List'
import Create from './forms/create/Create'
import Edit from './forms/edit/Edit'
import View from './forms/view/View'
// import Delete from './delete/Delete'
class Router extends Component {
constructor(props) {
super(props)
this.state = {
serverErrors: [],
}
}
getGraphQL = (type) => {
console.log('LIST QUERY', listQueries[type])
console.log('LIST QUERY NAME', listQueries[type].definitions[0].name.value)
console.log('CREATE MUTATION', createMutations[type])
console.log('CREATE MUTATION NAME', createMutations[type].definitions[0].name.value)
console.log('EDIT MUTATION', editMutations[type])
console.log('EDIT MUTATION NAME', editMutations[type].definitions[0].name.value)
console.log('VIEW QUERY', viewQueries[type])
console.log('VIEW QUERY NAME', viewQueries[type].definitions[0].name.value)
return {
listQuery: listQueries[type],
listQueryName: listQueries[type].definitions[0].name.value,
createMutation: createMutations[type],
createMutationName: createMutations[type].definitions[0].name.value,
editMutation: editMutations[type],
editMutationName: editMutations[type].definitions[0].name.value,
viewQuery: viewQueries[type],
viewQueryName: viewQueries[type].definitions[0].name.value,
}
}
renderComponentForAction = (params) => {
const { type, action } = params
const GQL = this.getGraphQL(type)
const {
listQuery, createMutation, editMutation, viewQuery,
} = GQL
// ADD QUERIES BASED ON URL
const ListWithGraphQL = graphql(listQuery)(List)
const CreateWithGraphQL = graphql(createMutation)(Create)
const EditWithGraphQL = compose(
graphql(viewQuery),
graphql(editMutation),
)(Edit)
const ViewWithGraphQL = graphql(viewQuery)(View)
if (!action) {
console.log('DEBUG: No action in URL, defaulting to ListView.')
return <ListWithGraphQL fromRouter={params} {...GQL} />
}
const componentFor = {
list: <ListWithGraphQL fromRouter={params} {...GQL} />,
create: <CreateWithGraphQL fromRouter={params} {...GQL} />,
edit: <EditWithGraphQL fromRouter={params} {...GQL} />,
view: <ViewWithGraphQL fromRouter={params} {...GQL} />,
// delete: <Delete fromRouter={params} {...GQL} />,
}
if (!componentFor[action]) {
console.log('DEBUG: No component found, defaulting to ListView.')
return <ListWithGraphQL fromRouter={params} {...GQL} />
}
return componentFor[action]
}
render() {
return this.renderComponentForAction(this.props.match.params)
}
}
Router.propTypes = {
match: PropTypes.shape({
params: PropTypes.shape({ type: PropTypes.string }),
}).isRequired,
}
export default compose(connect())(withApollo(Router))
如果此代码以后对某人有用。 我建议注释掉所有内容,除了呈现列表视图所需的代码。 首先,验证道具是否进入了“ hello world”的小视野。 然后,一旦在那里获得正确的数据,就将完成困难的部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.