Tired of debugging type errors in your state? Want up-to-date documentation for your React apps? Read on! When I first encountered , I felt a decent amount of despair: Why did I have to write what felt like more boilerplate code? When using it with React, why did I have to determine the type of every single prop, and the request and response objects for async calls? And what the hell were intersection and union types? TypeScript React After spending time working with TypeScript, however, I quickly fell in love with it. It saves me from wasting time on dumb type errors, provides dynamic self-documentation, and makes it far easier for my colleagues to understand the expectations set for the code at first glance. My interest in TypeScript grew as I explored different approaches to state management in React applications. I’m especially excited about React’s new , which I believe can be very powerful, especially when combined with and TypeScript. Context API GraphQL In October, my excitement composed itself into a talk for the meetup (for which I’m now also co-organizer), where I covered my approach to state management in React applications with TypeScript. Boston TypeScript But what about Redux? https://redux.js.org/ But before we get into all that: We need to talk briefly about . It’s well-established, arguably the default state management pattern for React by now. So why don’t we just use it? Redux Depending on your application’s needs, Redux can be overly complex/heavy-handed You may not want to use the Redux ecosystem, including action creators, reducers, etc. entire You wind up with tons of boilerplate code What’s the Context API and why do I care? I started using the Context API in some applications over Redux this year, and I found it elegant and fast to implement. The Context API is “an upgraded version of old concept of context in React which allow[s] components to share data outside the parent-child relationship,” aptly writes in “ ” Rakshit Soral Everything You Need to Know About React’s Context API. My own short definition? The Context API is a way to share state and avoid prop drilling (as of React 16.3). What it all boils down to is a clean, pretty way to share information across your application without sending it down through components that don’t care about it. My diagram of the Context API may be over-simplified, though you’ll see there’s really not too much more to it than this. You employ a , which is the root source of information to all components in the tree, and you also use a , whose responsibility involves taking data or functionality from the and feeding it directly to the components that require that information. Provider Consumer Provider First, you’ve got , which initializes and passes the context an initial value. In this example from the , returns an object with a Provider and Consumer. React.createContext Context API docs React.createContext const {Provider, Consumer} = React.createContext(defaultValue); The in the below code — also from the — accepts a value prop that represents the information, data, functions, etc., that get shared via context. Provider docs <MyContext.Provider value={/* some value */}> The in the following example — again, from the — wraps a function that takes in a value from the Provider and returns in the form of components that are privy to the ‘s information. Consumer docs JSX Provider <MyContext.Consumer> {value => /* render something based on the context value */}</MyContext.Consumer> What’s GraphQL and why do I care? GraphQL, like React, was created by . Unlike , GraphQL uses just single endpoint that allows you to fetch data via multiple queries at once. It allows you to request only the data you want, exactly when you want it. Facebook REST one https://graphql.org/ As you can see above, GraphQL also has a built-in type system that helps provide dynamic API self-documentation as the API grows and evolves. Even better, you can generate static types for your queries as part of the tooling system. Apollo Adding GraphQL to your app $ npm install --save apollo-boost react-apollo graphql gives you a bunch of packages right out of the box. Apollo Boost Getting a boost with Apollo is a caching GraphQL client that you can use with React (as well as with Angular and other frameworks) apollo-client is a standard, in-memory cache recommended for use with apollo-cache-inmemory apollo-client simply fetches GraphQL results from a GraphQL endpoint over an HTTP connection apollo-link-http exports the function, which allows you to write easily parseable strings for our queries and mutations graphql-tag gql contains bindings for using with React, and is just Facebook’s reference implementation of GraphQL. react-apollo apollo-client graphql Configuring the Apollo client Here’s an example from the : React Apollo docs import const client = new Here, you import , , and the . If you’d prefer to use a GraphQL endpoint other than the default endpoint, which resides on the same host as the client, accepts a configuration object. ApolloClient HttpLink InMemoryCache HttpLink What this means is, for example, if you’re using a microservice that lives on a different host, you’ll pass in a custom config object for your GraphQL endpoint. Next, you wrap your root component in , imported from . This gives each component in your application access to GraphQL via Apollo. The example below is also from the : ApolloProvider react-apollo React Apollo docs import ReactDOM.render( <ApolloProvider client={client}> <MyRootComponent /> </ApolloProvider>, document.getElementById('root'),); Generating types with Apollo $ npm i --save apollo-codegen The scripts I prefer to use are below: package.json "introspect": "apollo-codegen introspect-schema GRAPHQL_ENDPOINT --output PATH_TO_SCHEMA_FILE",// this fetches the schema and saves it in our project"generate": "apollo-codegen generate GLOB_PATH_TO_QUERY_FILES --schema PATH_TO_SCHEMA_FILE --target typescript --output PATH_TO_GENERATED_TYPES_FILE --add-typename --tag-name gql",// this generates type interfaces from our schema"typegen": "npm run introspect && npm run generate" In my script, I’m calling with my endpoint and requesting GraphQL to output my schema files to a specified file. introspect apollo codegen introspect-schema My script looks at my auto-generated schema file and my queries and mutations and generates types for my queries and mutations. generate And, finally, my script combines those two aforementioned scripts. typegen I run and I’m good to go with my GraphQL types! npm run typegen, Please note, again: This is my preferred approach. Everyone should, of course, feel free to configure their scripts however they feel is best! package.json Demo time I drank way too much coffee the other day and decided I wanted to rebuild and rebrand Amazon. Thankfully, I decided to start small. My partner just moved to Philadelphia, and folks have their own lingo for various things down there. Like this one: Jawn: noun, chiefly in eastern Pennsylvania, used to refer to a thing, place, person, or event that one need not or cannot give a specific name to. My Jawn Store MVP should eventually display a list of products with their prices and give me the ability to add things to my cart. I should also be able to remove items from my cart and see the updated total instantly. While I explain how to set up React Context with GraphQL and TypeScript in the rest of this article, you can also find the full source code . here For my prototype, I’m using , a terrific library for generating fake data. Faker.js hosts a endpoint, allowing me to get my fake data from a GraphQL endpoint. It offers me the following types to query: Faker.js FakerQL Post Product User Todo For my purposes, since I’m running a store, I’ll be fetching data via FakerQL for products to sell. My app also uses the following technologies: TypeScript with , a bundler which supports TS right out of the box Parcel.js React’s Context API Setting up my GraphQL client Getting my store ready for the grand opening! My app already has all the necessary Apollo dependencies installed, and these scripts are included in my : package.json "scripts": { "test": "npm run test", "dev": "parcel ./index.html", "introspect": "apollo-codegen introspect-schema https://fakerql.com/graphql --output ./data/models/index.json", "generate": "apollo-codegen generate ./data/**/*.ts --schema ./data/models/index.json --target typescript --output ./data/models/index.ts --add-typename --tag-name gql", "typegen": "npm run introspect && npm run generate", "build": "tsc"} You’ll notice the use of the FakerQL endpoint and a path to a folder where I’m both auto-generating schema models and setting up my query types. data And here’s the actual structure for my folder: data - data - formatters - models - queries My are functions for calculating prices in different countries (already implemented). When I run my script, Apollo will output the schema into an file in my folder. All files in the folder will wind up being auto-generated. formatters introspect index.json models models When I run my script, Apollo will look at my queries, in conjunction with the endpoint schema, and output the types onto an file in my folder. generate index.ts models Next, I need to create an instance of so I can use its capabilities. ApolloClient // ./index.tsximport const client = new class Just like in the example we saw before, we’re using , , and the . I’m passing in a URI configuration object with the FakerQL endpoint. ApolloClient HttpLink InMemoryCache I’m also ensuring that the root component is wrapped in , and that all components in the tree can therefore take advantage of GraphQL. ApolloProvider Let’s get down to business: I need a query to fetch all the products via FakerQL. I prefer to have a file for each query in my data folder. // data/queries/JAWN_QUERY.ts import export Here, I’m using to drop my query into an easily readable string. When I look at the FakerQL docs, they tell me I can query and specify the above fields — among others — to be returned for each product. gql allProducts When I run , here are the types that get generated: npm run typegen export export represents the type for an individual project or item, and is the type for an array or list of products in our store. These types will be useful for setting up our context and typing components that wind up taking advantage of this data. FindJawnProducts_allProducts FindJawnProducts Before I get our components using data from GraphQL, I stop to ask myself: What other information do I want besides the product details fetched from FakerQL? As it turns out, I want to support two different markets: the U.S. and the U.K. In order to provide the correct calculations for product prices, I need my components to be aware of my market. In this case, I’ll pass the market down as a prop into the root component. class const HotApp = hot(module)(App);render(<HotApp market="US" But I don’t want to drill props down from the root component just to provide awareness about my market. I also have two components — and — that potentially need to know about the products I’m fetching from my API, but I don’t want to pass that data down as a prop, either. JawnList Cart My reasons? Prop drilling can get incredibly messy as your application increases in size. My MVP could grow into a much bigger app, and I don’t want to wind up passing details down through components that don’t care about them. Enter the Context API! Context API magic! I create a file called , where I define and create my context for the application: JawnContext.tsx This is where the Apollo-generated types will start to come in handy. will be an array of FakerQL products. will take in a FakerQL product as an argument and add it to the . will do exactly what it sounds like. And, finally, the can be typed as either or . Cart addToCart Cart removeFromCart market "US" "UK" Then, works its magic! ( , by the way, is my default value for the context). React.createContext null Next, let’s hook up my context to my root component. You’ll notice that is typed to — the context type — since one of the component’s props is , which I now want to derive from context. App JawnState market You’ll also notice that I’m wrapping the component with and its value object, which contains the values of each of the context properties — the implementations of and , the passed into the root, and the current state of the cart. JawnContext.Provider addToCart removeFromCart market Moving on to the consumers: This is personal preference here — some folks prefer to create new functions to wrap each consuming component — but I want to set up a reusable provider here so I can easily compose it with the GraphQL provider and the consuming component whenever necessary. WithJawnContext Here, my extend , the type for the context, and the function accepts a React component as a child. It’s then returning a child, wrapped by , which spreads the given props and context state within it. Props JawnState JawnContext.Consumer To allow to successfully consume my context in a type-safe fashion, I need to define as a child that combines attributes from the context and GraphQL’s autogenerated data type, . JawnList JawnListType JawnState FindJawnProducts This gives me access to the data from my GraphQL endpoint, as well as the and from my context. market addToCart At the bottom of the above code, you’ll see I’ve created a function to make the necessary GraphQL query for the product data. I’m composing that with the provider and my component. React Apollo gives me , the generic type for a component wrapped by . withJawnContext ChildDataProps ApolloProvider Similarly, I need to allow Cart to consume the context. Here, I’m composing the provider with — typed to — which gives me access to , , and from context. withJawnContext Cart JawnState market cart removeFromCart And that’s about it! My application allows users to add and remove items from their carts and view updated total prices, and I get to avoid prop-drilling across my application. I win! Takeaways Apollo helps us query a single endpoint and generate GraphQL types for our schema, queries, and mutations The Context API, working together with TypeScript, provides a type-safe, lightweight way to share state and data without drilling down props A version of this article was originally published on . You can find the full source code for the Jawn Store . lilydbarrett.com here Additional useful resources: Introduction to GraphQL Apollo Client docs ( ) “Everything you need to know about React’s Context API” Rakshit Soral React Context docs TypeScript docs