Last active
March 12, 2020 00:20
-
-
Save duwerq/b16d8c8739f95ca52509f7a471b4d1d4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const dashboardQueries = [ | |
{ | |
queryEnhancer: { | |
query: gql(queries.getUser), | |
fetchPolicy: 'cache-first', | |
dataKey: 'user', | |
queryKey: 'getUser' | |
} | |
}, | |
] | |
const DashboardComponent = WrappedComponent(Dashboard, dashboardQueries); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import { withApollo } from 'react-apollo'; | |
export default options => (WrappedComponent) => { | |
class QueryEnhancer extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
[`${this.props.options.dataKey}`]: {}, | |
[`${this.props.options.dataKey}Loading`]: false, | |
[`${this.props.options.dataKey}Error`]: null, | |
[`${this.props.options.dataKey}NetworkStatus`]: 7 | |
}; | |
} | |
componentDidMount() { | |
// If you're using React-Native, make sure to change this.props.location.state to this.props.navigation.state | |
const { | |
params, | |
} = this.props.location.state || {}; | |
if (this.props.options && this.props.options.fetchPolicy === 'cache-and-network') { | |
this.watchQuery(params || {}); | |
} | |
this._query(params || {}); | |
} | |
componentWillUnmount() { | |
if (Object.keys(this.observable).length > 0) this.observable.unsubscribe(); | |
} | |
watchQuery = async (m) => { | |
const { options, client } = this.props; | |
const watchedQuery = client.watchQuery({ | |
query: options.query, variables: m | |
}); | |
this.observable = watchedQuery.subscribe({ | |
next: async ({ data }) => { | |
let freshData = data; | |
if (typeof options.resolver === 'function') { | |
freshData = await options.resolver(data[options.queryKey], client); | |
} | |
this.setState({ | |
[`${options.dataKey}`]: freshData[options.queryKey], | |
}); | |
} | |
}); | |
} | |
observable = {} | |
_query = async (m, watchQuery) => { | |
const { options, client } = this.props; | |
if (this.state[`${options.dataKey}Loading`] === false) { | |
if (options.fetchPolicy === 'cache-only') { | |
const { data: cacheData } = await client.query({ | |
query: options.query, | |
variables: m, | |
fetchPolicy: 'cache-only' | |
}); | |
this.setState({ [`${this.props.options.dataKey}`]: cacheData[options.queryKey], [`${this.props.options.dataKey}Loading`]: false }); | |
} else if (typeof options.resolver === 'function') { | |
this.setState({ [`${options.dataKey}Loading`]: true }); | |
try { | |
const newQuery = await client.query({ | |
query: options.query, | |
variables: m, | |
fetchPolicy: 'no-cache' | |
}); | |
if (newQuery && newQuery.data[options.queryKey]) { | |
const resolvedData = await options.resolver(newQuery.data[options.queryKey], client); | |
if (resolvedData) { | |
client.writeQuery({ | |
query: options.query, | |
data: resolvedData | |
}); | |
} | |
this.setState({ | |
[`${options.dataKey}Loading`]: false, | |
[`${options.dataKey}`]: resolvedData[options.queryKey], | |
[`${options.dataKey}NetworkStatus`]: newQuery.networkStatus | |
}); | |
} | |
} catch (error) { | |
this.setState({ | |
[`${options.dataKey}Loading`]: false, | |
[`${options.dataKey}Error`]: error, | |
// [`${options.dataKey}NetworkStatus`]: newQuery.networkStatus | |
}); | |
} | |
} else { | |
this.setState({ [`${options.dataKey}Loading`]: true }); | |
try { | |
const newQuery = await client.query({ | |
query: options.query, | |
variables: m, | |
fetchPolicy: options.fetchPolicy === 'cache-and-network' ? 'network-only' : options.fetchPolicy | |
}); | |
if (newQuery) { | |
this.setState({ | |
[`${options.dataKey}Loading`]: false, | |
[`${options.dataKey}`]: newQuery.data[options.queryKey], | |
[`${options.dataKey}NetworkStatus`]: newQuery.networkStatus | |
}); | |
} | |
} catch (error) { | |
this.setState({ | |
[`${options.dataKey}Loading`]: false, | |
[`${options.dataKey}Error`]: error, | |
// [`${options.dataKey}NetworkStatus`]: newQuery.networkStatus | |
}); | |
} | |
} | |
} return null; | |
} | |
render() { | |
return (<WrappedComponent | |
{...{ | |
...this.props, | |
...this.state, | |
options: {}, | |
[`${this.props.options.dataKey}Refetch`]: m => this._query(m) | |
// [`${this.props.options.dataKey}`]: m => this._query(m) | |
}} | |
/>); | |
} | |
} | |
QueryEnhancer.displayName = `QueryEnhancer(${options.dataKey})`; | |
return withApollo(props => <QueryEnhancer {...{ ...props, options }} />); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import flow from 'lodash/flow'; | |
// import MutationEnhancer from './MutationEnhancer'; | |
import QueryEnhancer from './QueryEnhancer'; | |
// const mutationParams = ({ | |
// fetchPolicy, | |
// mutationKey, | |
// mutation, | |
// mutationUpdate | |
// }) => MutationEnhancer({ | |
// mutation, mutationUpdate, mutationKey, fetchPolicy | |
// }); | |
const queryEnhancerParams = ({ | |
fetchPolicy, | |
queryKey, | |
query, | |
returnFn, | |
dataKey, | |
subscribe, | |
updateQuery, | |
resolver, | |
}) => QueryEnhancer({ | |
fetchPolicy, | |
queryKey, | |
query, | |
returnFn, | |
dataKey, | |
subscribe, | |
updateQuery, | |
resolver | |
}); | |
const createQuery = ({ | |
queryEnhancer: query => queryEnhancerParams(query) | |
}); | |
const graphqlQueries = queries => queries.map((fn) => { | |
const queryType = Object.keys(fn)[0]; | |
const params = fn[`${queryType}`]; | |
const composeQuery = createQuery[`${queryType}`]; | |
const composedQuery = composeQuery(params); | |
return composedQuery; | |
}); | |
const wrappedComponent = (component, fnQueries) => (fnQueries ? | |
flow(...graphqlQueries(fnQueries))(component) : | |
component | |
); | |
// class WrappedComponet extends React.Component { | |
// queryChildren | |
// } | |
export default wrappedComponent; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment