我可以使用 HOC 来用 graphql 和 redux 包装组件吗
Can I use HOC to wrap component with graphql and redux
我有很多模板组件,它们在使用方式上彼此相似。
在呈现到页面之前,模板组件被包装在 graphql 中并连接到 redux。
我想创建一个 HOC 来包装我的模板,这样我就不会每次都创建一个新容器来将模板连接到数据。
像这样:
这是我的页面组件,我尝试用 gqlList HOC:
包装 AppointmentsListTemplate 模板
import React from 'react'
import { AdminTemplate, AppointmentsListTemplate } from 'components'
import { gqlList } from 'containers'
import {qyListAppointments} from 'services/gqlQueries/Appointments'
const AppointmentsListTemplateWrapped = gqlList(AppointmentsListTemplate, qyListAppointments)
const AdminAppointmentsPage = (props) => {
return (
<AdminTemplate>
<AppointmentsListTemplateWrapped />
</AdminTemplate>
)
}
export default AdminAppointmentsPage
这是我的 gqlList HOC:
import React, {Component} from 'react'
import { graphql } from 'react-apollo'
import { connect } from 'react-redux'
import { saveQueryVars } from 'store/helper/actions'
const gqlList = (WrappedComponent, gqlQuery) => {
const GQL = graphql(gqlQuery)(WrappedComponent)
return connect(null, {
saveQueryVars,
})(GQL)
}
export default gqlList
但是 graphql 连接器部分抛出这个错误:
Uncaught TypeError: Cannot read property 'displayName' of undefined
at getDisplayName (react-apollo.browser.umd.js:250)
at wrapWithApolloComponent (react-apollo.browser.umd.js:266)
at new eval (gqlList.js:22)
at eval (createClassProxy.js:95)
at instantiate (createClassProxy.js:103)
at Unknown (eval at proxyClass (createClassProxy.js:NaN), :4:17)
at eval (ReactCompositeComponent.js:303)
at measureLifeCyclePerf (ReactCompositeComponent.js:73)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner
我做错了什么?
据我所知,您的代码似乎没有任何问题。我也会排除 redux 作为错误的来源。但这是我的建议:
检查您的 GraphQL 查询 (gqlQuery),以便它获得所需的内容,并且可以 return 您需要的内容。我怀疑它需要一些参数但没有获得正确的参数类型 - 导致类型错误。
这是一个如何传递参数的示例(没有 redux):
const Data = graphql(fetchData, { options: {variables: {id: this.getId()} }})(Thing);
这里,fetchData 需要一个事物的 ID 和关于那个事物的 returns 数据。然后你可以渲染 <Data/>.
您可能想通过向其中添加查询和变量 (saveQueryVars) 来改进您的问题。另外,请提及 react-apollo 的版本,因为这是抛出错误的模块。作为旁注,来自 Apollo 客户端的错误消息不是很有帮助。
您可以将它们链接在一起:
import { changeFoo } from './myReduxActions';
const QUERY = gql`{ FindSomething { Id, Value }}`;
const myComponent = connect(
store => ({
foo: store.fooReducer.foo
}),
dispatch => ({
changeFoo: (val) => dispatch(changeFoo(val))
})
)(graphql(QUERY)(
{props.data.loading && return <div>Loading...</div>}
let myNewFoo = 'abc';
return props.data.FindSomething ?
<div>{`Id is ${props.data.FindSomething.Id}, redux store value foo is ${props.foo}`}
<div onClick={() => props.ChangeFoo(myNewFoo)}></div></div> :
props.data.error ? <div>Error {props.data.error}</div> : null;
));
所以你可以做 connect(graphql(pureComponent)))
或者写成 connect => graphql => component
。你可以改变graphql和连接的顺序。
我有很多模板组件,它们在使用方式上彼此相似。 在呈现到页面之前,模板组件被包装在 graphql 中并连接到 redux。 我想创建一个 HOC 来包装我的模板,这样我就不会每次都创建一个新容器来将模板连接到数据。 像这样:
这是我的页面组件,我尝试用 gqlList HOC:
包装 AppointmentsListTemplate 模板import React from 'react'
import { AdminTemplate, AppointmentsListTemplate } from 'components'
import { gqlList } from 'containers'
import {qyListAppointments} from 'services/gqlQueries/Appointments'
const AppointmentsListTemplateWrapped = gqlList(AppointmentsListTemplate, qyListAppointments)
const AdminAppointmentsPage = (props) => {
return (
<AdminTemplate>
<AppointmentsListTemplateWrapped />
</AdminTemplate>
)
}
export default AdminAppointmentsPage
这是我的 gqlList HOC:
import React, {Component} from 'react'
import { graphql } from 'react-apollo'
import { connect } from 'react-redux'
import { saveQueryVars } from 'store/helper/actions'
const gqlList = (WrappedComponent, gqlQuery) => {
const GQL = graphql(gqlQuery)(WrappedComponent)
return connect(null, {
saveQueryVars,
})(GQL)
}
export default gqlList
但是 graphql 连接器部分抛出这个错误:
Uncaught TypeError: Cannot read property 'displayName' of undefined at getDisplayName (react-apollo.browser.umd.js:250) at wrapWithApolloComponent (react-apollo.browser.umd.js:266) at new eval (gqlList.js:22) at eval (createClassProxy.js:95) at instantiate (createClassProxy.js:103) at Unknown (eval at proxyClass (createClassProxy.js:NaN), :4:17) at eval (ReactCompositeComponent.js:303) at measureLifeCyclePerf (ReactCompositeComponent.js:73) at ReactCompositeComponentWrapper._constructComponentWithoutOwner
我做错了什么?
据我所知,您的代码似乎没有任何问题。我也会排除 redux 作为错误的来源。但这是我的建议:
检查您的 GraphQL 查询 (gqlQuery),以便它获得所需的内容,并且可以 return 您需要的内容。我怀疑它需要一些参数但没有获得正确的参数类型 - 导致类型错误。 这是一个如何传递参数的示例(没有 redux):
const Data = graphql(fetchData, { options: {variables: {id: this.getId()} }})(Thing);
这里,fetchData 需要一个事物的 ID 和关于那个事物的 returns 数据。然后你可以渲染 <Data/>.
您可能想通过向其中添加查询和变量 (saveQueryVars) 来改进您的问题。另外,请提及 react-apollo 的版本,因为这是抛出错误的模块。作为旁注,来自 Apollo 客户端的错误消息不是很有帮助。
您可以将它们链接在一起:
import { changeFoo } from './myReduxActions';
const QUERY = gql`{ FindSomething { Id, Value }}`;
const myComponent = connect(
store => ({
foo: store.fooReducer.foo
}),
dispatch => ({
changeFoo: (val) => dispatch(changeFoo(val))
})
)(graphql(QUERY)(
{props.data.loading && return <div>Loading...</div>}
let myNewFoo = 'abc';
return props.data.FindSomething ?
<div>{`Id is ${props.data.FindSomething.Id}, redux store value foo is ${props.foo}`}
<div onClick={() => props.ChangeFoo(myNewFoo)}></div></div> :
props.data.error ? <div>Error {props.data.error}</div> : null;
));
所以你可以做 connect(graphql(pureComponent)))
或者写成 connect => graphql => component
。你可以改变graphql和连接的顺序。