apollo-mantra v1.6.4
Apollo and Redux Tools
This set of helpers facilitates the use of GraphQL and Apollo with your React/Redux application.
It allows you to:
- Define queries and mutations using object notation for better code clarity
- Copy query results to redux store for easier optimistic callbacks
- Use higer order elements to display messages based on query easier
Server
The server functionality has been moved to: apollo-modules
Client
Client helpers exists in the apollo-mantra module and focus on easy integration of apollo in redux projects.
Following is a list of helpers:
Query and Mutation Helpers
These helpers provide a possibility to define queries and mutations in object format, which facilitates the code readibility. Following is the structure of the query.
interface IQuery {
  query: string;
  variables?: Object;
  pollInterval: number; // watch query only
  returnPartialData: boolean;  // watch query only
  forceFetch: boolean;
  optimisticCallback?: (dispatch: Function, state: () => any) => void;
  thenCallback?: (data: any, dispatch: Function, state: () => any) => void;
  errorCallback?: (errors: any, dispatch: Function, state: () => any) => void;
  catchCallback?: (error: any, dispatch: Function, state: () => any) => void;
  finalCallback?: (dispatch: Function, state: () => any) => void;
}- query(query: IQuery): voidcreate query using object definition
- watchQuery(query: IQuery): voidcreate watch query using object definiton and return an observer
- mutation(query: IQuery): voidcreate mutation using object definition
The query returns an action that should be dispatched via redux store, watchQuery returns an observer.
Application Helpers
- createApp(context: any, options: IOptions): anycreate a new apollo based application and expose context into all redux and apollo function calls
Container Helpers
- connect<T>(funcs: IConnectFunctions): (component: any) => React.StatelessComponent<T>use as standard redux or apollo connect function, but all realted functions will now have application context as their first parameter:- mapStateToProps(context: any, state: any, ownProps: any): void
- mapDispatchToProps(context: any, dispatch: any, ownProps: any): void
- mergeProps(context: any, state: any, ownProps: any): void
- mapQueriesToProps(context: any, props: any): void
- mapMutationsToProps(context: any, props: any): void
 
- loadingContainer(component: any, keys?: string[]): anyhigher order component that shows a loading control while queries are loading
- loadingContainer(component: any, loading?: any, keys?: string[]): anyhigher order component that shows a loading control while queries are loading
- queriesFinished(state: IApolloState): booleandecides whether all queries currently finished loading
Reducer Helpers
Please see the reducer example.
- copyQuery(state: Object, stateKey: string, queryResult: Object[], queryKey?: string, overwrite?: boolean): Objectcopies a query result into the store
- isQuery(action: any, queryName: string): booleanchecks whether a given action represent a query call with a given name
- getQuery<T>(action: any): stringobtains a result of a query with a specified name
- isMutation(action: any, queryName: string): booleanchecks whether a given action represent a query call with a given name
- getMutation<T>(action: any): stringobtains a result of a mutation with a specified name
Examples
List of examples of common uses of our helpers
Reducer
This is how you can copy apollo query results to the store.
import { getQuery, copyQuery } from 'apollo-mantra';
import update from 'react-addons-update';
export interface IMarkingState {
  showMarked: boolean;
  showPending: boolean;
  solutions: Cs.Entities.ISolution[];
  current: { [index: string]: Cs.Entities.ISolution };
}
export default function reducer(state: IMarkingState = { showMarked: false, showPending: false, solutions: [], practical: {}, current: null }, action: any) {
  // when we execute a specific query, we want to copy its values nto the store
  switch (getQuery(action)) {
    case 'practical':
      // the copy query will copy the query reult into the key 'practical' and add a new
      // field under its '_id'. e.g. practical.id1 = result
      return copyQuery(state, 'practicals', action.result.data.practical, '_id');
    case 'markingSolutions':
      // we want to merge results with what is currently in the store
      const res = action.result.data.markingSolutions;
      const eliminateDuplicates = (s: Cs.Entities.ISolution) => !res.find((r: Cs.Entities.ISolution) => r._id === s._id);
      if (res && res.length) {
        let output = res.concat(state.solutions.filter(eliminateDuplicates));
        return update(state, { solutions: { $set: output } });
      }
      return state;
  }
  switch (action.type) {
    // other reducer stuff
  }
  return state;
}Calling a query or a mutation
const mutation = mutation({
  query: `mutation requestResetPassword($email: String!) {
    requestResetPassword(email: $email)
  }`,
  variables: {
    email
  },
  errorCallback: (err) => {
    if (err.message === 'User not found [403]') {
      dispatch(actions.showError('accounts.error.emailNotFound'));
    } else {
      dispatch(actions.showError('accounts.error.unknownError'));
    }
    if (callback) { callback(); }
  },
  thenCallback: (data: any) => {
    dispatch(actions.showError('accounts.messages.passwordResetEmailSent'));
    if (callback) { callback(); }
  }
});
dispatch(mutation);8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago