Files
talk/client/coral-framework/hocs/withQuery.js
T

58 lines
1.7 KiB
JavaScript

import * as React from 'react';
import {graphql} from 'react-apollo';
import {getQueryOptions, resolveFragments} from 'coral-framework/services/graphqlRegistry';
import {getDefinitionName, separateDataAndRoot, getResponseErrors} from '../utils';
const withSkipOnErrors = (reducer) => (prev, action, ...rest) => {
if (action.type === 'APOLLO_MUTATION_RESULT' && getResponseErrors(action.result)) {
return prev;
}
return reducer(prev, action, ...rest);
};
/**
* Exports a HOC with the same signature as `graphql`, that will
* apply query options registered in the graphRegistry.
*/
export default (document, config = {}) => (WrappedComponent) => {
config = {
...config,
options: config.options || {},
props: config.props || (({data}) => separateDataAndRoot(data)),
};
const wrappedOptions = (data) => {
const base = (typeof config.options === 'function') ? config.options(data) : config.options;
const name = getDefinitionName(document);
const configs = getQueryOptions(name);
const reducerCallbacks =
[base.reducer || ((i) => i)]
.concat(...configs.map((cfg) => cfg.reducer))
.filter((i) => i);
const reducer = withSkipOnErrors(
reducerCallbacks.reduce(
(a, b) => (prev, ...rest) =>
b(a(prev, ...rest), ...rest),
));
return {
...base,
reducer,
};
};
let memoized = null;
const getWrapped = () => {
if (!memoized) {
memoized = graphql(resolveFragments(document), {...config, options: wrappedOptions})(WrappedComponent);
}
return memoized;
};
return (props) => {
const Wrapped = getWrapped();
return <Wrapped {...props} />;
};
};