smallorange-graphql-react-prefetcher
v1.0.9
Published
GraphQl prefetcher for react components
Downloads
5
Readme
Small Orange Graphql React Prefetcher
Usage
You need provide a graphql transport layer that returns an Observable like. It would be server side (like this sample), or an ajax function which talks with a graphql backend, but its important to keep same args input of the sample below, and might returns an Observable with the result:
import {
graphql,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt
} from 'graphql';
import {
Observable
} from 'rxjs';
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
name: {
type: GraphQLString,
args: {
age: {
type: GraphQLInt
}
},
resolve: (root, {
age
}, context, info) => {
return age ? `Rohde - ${age}` : 'Rohde';
}
}
}
}),
});
export graphQlRunner = args => {
const {
query,
root = {},
context = {},
variables = {}
} = args;
if (!query) {
return Observable.throw(new Error('No query provided.'));
}
return Observable.create(subscriber => {
graphql(schema, query, root, context, variables)
.then(response => {
if (response.errors) {
return subscriber.error(new Error(response.errors.join()));
}
subscriber.next(response);
subscriber.complete();
});
});
}
React components can have three static properties or methods, "queries", "dependencies" and "info":
// set component queries
queries: {[queryName: string]: {query: string, args?: object, callback?: function}}
queries: {[queryName: string]: Observable<{query: string, args?: object, callback?: function}>}
queries: {[queryName: string]: args => {query: string, args?: object, callback?: function}}
queries: {[queryName: string]: args => Observable<{query: string, args?: object, callback?: function}>}
queries(props): {[queryName: string]: {query: string, args?: object, callback?: function}}
queries(props): {[queryName: string]: Observable<{query: string, args?: object, callback?: function}>}
queries(props): {[queryName: string]: args => {query: string, args?: object, callback?: function}}
queries(props): {[queryName: string]: args => Observable<{query: string, args?: object, callback?: function}>}
// set component dependencies
dependencies(props): {[dependencyName: string]: {
component: React.Component | string,
args?: {
[queryName: string]: {
[arg: string]: any
}
},
props?: {
[arg: string]: any
}
}}
dependencies(props): {[dependencyName: string]: Observable<{
component: React.Component | string,
args?: {
[queryName: string]: {
[arg: string]: any
}
},
props?: {
[arg: string]: any
}
}>}
dependencies: {[dependencyName: string]: {
component: React.Component | string,
args?: {
[queryName: string]: {
[arg: string]: any
}
},
props?: {
[arg: string]: any
}
}}
dependencies: {[dependencyName: string]: Observable<{
component: React.Component | string,
args?: {
[queryName: string]: {
[arg: string]: any
}
},
props?: {
[arg: string]: any
}
}>}
dependencies: {[dependencyName: string]: Array<{
component: React.Component | string,
args?: {
[queryName: string]: {
[arg: string]: any
}
},
props?: {
[arg: string]: any
}
}>}
// export some value to prefetcher
info: object;
info(props, resolvedQueries): object;
React Component Sample
export class Child extends React.Component {
static queries(props){
return {
name: `name`
dog: `dog`
}
}
render() {
const {
queries = {}
} = this.props;
return (queries.dog && queries.name )? <h1>{queries.dog} belongs to {queries.name}</h1> : null;
}
}
export class App extends React.Component {
static queries = {
name: args => {
query: `name(age: $age)`,
args: {
age: args.age
}
}
};
static dependencies(props){
return {
child: {
component: 'Child'
},
children: [{
component: 'Child'
}, {
component: 'Child'
}]
};
}
static info = {
title: 'Page Title'
};
render() {
const {
queries = {},
dependencies = {},
args = {}
} = this.props;
const Child = dependencies.child || null;
return (
<section>
<h1>{queries.name}</h1>
<h2>{args.customArgs}</h2>
{Child ? <Child/> : null}
{_.map(dependencies.children, (Component, key) => (
Component ? <Component key={key}/> : null
))}
</section>
);
}
}
Prefetcher usage
import {
renderToStaticMarkup
} from 'react-dom/server';
import {
Prefetcher
} from 'smallorange-graphql-react-prefetcher';
import graphql from 'graphqlTransporter'; // see above
import * as components from 'components';
const descriptor = {
app: {
component: 'App' || components.App,
args: {
name: {
age: 20
}
}
},
child: {
component: 'Child' || components.Child
}
};
const prefetcher = new Prefetcher(graphql, components /* just provide this if you intend to lookup components via strings, in descriptor */);
prefetcher.run(descriptor.app)
.subscribe(response => {
// when there is info exported, prefetcher returns and object containing info, and component
const {
component: Component,
info
} = response;
console.log(info); // info exported from "static info"
renderToStaticMarkup(<Component/>); // Component with prefetched data from queries and resolved dependnecies
});
// OOOR
prefetcher.run(descriptor.child)
.subscribe(response => {
// when there is no info exported, prefetcher returns just the component
const Component = response;
renderToStaticMarkup(<Component/>); // Component with prefetched data from queries
});
// OOOR you can optionally run a single query with
prefetcher.query(descriptor.app.queries.name)
.subscribe(/* you know what to do */);
Final Words
If you have any questions, see the specs, otherwise contact me at [email protected]. I intend to write a better documentation, as soon I have more time.