Giter Club home page Giter Club logo

next-apollo-provider's Introduction

next-apollo-provider

A helper to make an ApolloProvider available as a high order component for next.js pages.

Install

npm install next-apollo-provider --save

Setup

By default the provider will create and cache an ApolloClient for each unique URI provided to a NetworkInterface, so its best to create your own withApollo.js wrapper with your settings and not apply nextApolloProvider to components directly.

Create a basic Wrapper

Provide a URL that points to a GraphQL server and a default configuration and network interface will be automatically created.

import nextApolloProvider from 'next-apollo-provider';

export default nextApolloProvider(process.env.GRAPHQL_URL);

Ensure you make the environment variable available to the client - see with-universal-configuration for an example.

Create from an ApolloClient settings object

Provide an ApolloClient settings object to customise the connection. You should not set initialState and ssrMode they will be automatically attached. All other options are supported including networkInterfaces and middleware. By default an ApolloClient will be created and reused across requests for each unique networkInterface.uri provided, you can supply an additional name property if you need multiple clients and settings per endpoint.

import nextApolloProvider from 'next-apollo-provider';
import { createNetworkInterface } from 'react-apollo';

export default nextApolloProvider({
  connectToDevTools: (process.browser && process.env.NODE_ENV !== 'production'),
  dataIdFromObject: (result) => (result.id || null),
  networkInterface: createNetworkInterface({
    uri: process.env.GRAPHQL_URL,
    opts: {
      credentials: 'same-origin'
    }
  })
});

Create from a function that returns settings

You can provide a function that returns a settings object for more control. You will need to set the provided initialState and ssrMode yourself. The request context will be available on the initial server request to access headers etc.

import nextApolloProvider from 'next-apollo-provider';
import { createNetworkInterface } from 'react-apollo';

export default nextApolloProvider((initialState, ssrMode, context)=>{

  let networkInterface = createNetworkInterface({
    uri: process.env.GRAPHQL_URL,
    opts: {
      credentials: 'same-origin'
    }
  });
    
  networkInterface.use([{
    applyMiddleware(req, next) {
      // Do some middleware such as authentication headers.
      next();
    }
  }]);
  
  return {
    initialState,
    ssrMode,
    connectToDevTools: (process.browser && process.env.NODE_ENV !== 'production'),
    dataIdFromObject: (result) => (result.id || null),
    networkInterface
  });

Use a function that returns an ApolloClient

If you need more control your settings function can return a getApolloClient(initialState, ssrMode, context) function which should return your own ApolloClient instance.

import nextApolloProvider from 'next-apollo-provider';
import { ApolloClient, createNetworkInterface } from 'react-apollo';

let apolloClient = null;

function getApolloClient(initialState, ssrMode){
  let settings = {
    initialState,
    ssrMode,
    connectToDevTools: (process.browser && process.env.NODE_ENV !== 'production'),
    dataIdFromObject: (result) => (result.id || null),
    networkInterface: createNetworkInterface({
      uri: process.env.GRAPHQL_URL,
      opts: {
        credentials: 'same-origin'
      }
    })
  };

  if (!process.browser) {
    return new ApolloClient(settings);   
  } else if(apolloClient) {
    return apolloClient;
  } else {
    apolloClient = new ApolloClient(settings); 
    return apolloClient;
  }   
}

export default nextApolloProvider(()=>(getApolloClient));

Redux Integration

Provide a getReduxStore(client, initialState) function as the second parameter and return a reduxStore to use a custom Redux store.

import nextApolloProvider from 'next-apollo-provider';
import { createNetworkInterface } from 'react-apollo';

const apolloClientSettings = {
  networkInterface: createNetworkInterface({
    uri: process.env.GRAPHQL_URL,
  })
};

let reduxStore = null;

function getReduxStore(client, initialState){
  ... TODO
  return reduxStore;
}
export default nextApolloProvider(apolloClientSettings, getReduxStore);

Usage

Use the withApollo HOC you created to wrap a next.js page, compose with graphql as required. The server needs to evaluate getInitialProps twice to fetch the initialSate, so use the provided initialState property to detect when the server has data to prevent the rendering of multiple <Head> tags for example.

import { gql, graphql, compose } from 'react-apollo';
import withApollo from './withApollo';

const Posts = ({ initialState, apolloClient })=>{
  return <div>{ initialState ? 'We have data!' : 'Server is loading data!'}</div>;
}

export default compose(
  withApollo, 
  graphql(gql`
    query PostsQuery {
      post {
        id
      }
    }
  `)
)(Posts);

Build & Run Examples

The examples in /pages use an API at graph.cool

Set an environment variable for GRAPHQL_URL=https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn

The module uses a simple next boilerplate and exports next-apollo-provider from /lib/next-apollo-provider, run with npm start dev, build with next build.

TODO

  • Some tests
  • Custom client example
  • Redux example

next-apollo-provider's People

Contributors

acorcutt avatar

Stargazers

 avatar  avatar

Watchers

 avatar

next-apollo-provider's Issues

process.env is not set on the client

babel-plugin-transform-define is not the right solution, we don't get the env inside the module, either require the default url to be set or figure out how to get a real process.env on the client.

Add url to props

I think we need to pass the url through to props so its available to the server.

Allow multiple client instances

It currently uses a single client instance when not providing your own, so you can't connect to multiple endpoints.

We should store multiple clients when needs so either we need a key on each setup or generate a unique id from the settings, maybe use a hash or a combination of uri + other params.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.