繁体   English   中英

使用Apollo Client 2.0时,是否有办法将动态GraphQL查询传递给装饰有graphql()的组件?

[英]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} />
})

我想我知道了。

  1. 我有一个读取this.props.match.params的路由器组件,以获取视图类型和请求的操作

  2. 利用这些信息,我只能创建一个List,Create,Edit和View Component,并为每个组件提供所需的查询。

  3. 我创建了一个函数,该函数可以获取所提供类型的所有查询和变异。

  4. 实际上,仅使用诸如<List />类的组件并用graphql()对其进行包装,并graphql()提供刚刚确定的正确查询或突变是非常简单的。

  5. 现在,使用正确的数据填充this.props.data来安装组件

  6. 我散布了所有查询和变异,以防万一我需要它们。 我怀疑当我阅读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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM