Yle’s news app had more than 200,000 weekly active users, but years of added features had made its code and startup process complex. Linnanen found more than 15 API calls involved in startup, with Redux and Redux Saga helping keep local and remote data in sync. He built a one-week proof of concept that combined REST data behind a GraphQL gateway and reduced startup to one or two calls.
GraphQLifying React Native App
Speaker
Juha Linnanen, Head of Mobile Development at Gofore, explains how his team brought GraphQL and Apollo into Yle’s React Native app at React Native EU 2020.
The team chose a JVM-based CraftQL server for the production API and kept article content on its existing optimized REST endpoint. Client-side local resolvers fetched articles with Axios and wrote them into Apollo’s cache. Because optional fields could be missing, Linnanen’s team built a schema enforcement function to supply defaults and add __typename; he notes this approach was tricky and local resolvers were deprecated in Apollo Client 3.
Type policies let the team look up an article by ID while returning the fuller article query data, including related concepts. Linnanen separates state into remote data for Apollo queries, shared local data for reactive variables, and component-only data for React hooks. Reactive variables update queries that depend on them, but the team had to persist their values separately in AsyncStorage.
Linnanen used React Native Debugger to inspect Apollo queries, mutations, and normalized cache contents. He also described an early Flipper plugin with a working cache tab. For tests, Apollo’s MockedProvider could pair requests with responses, but its mocks did not cover local resolvers, which instead required passing resolvers to the provider.
The app was still in active development, but the team reported clearer API contracts through the GraphQL schema and TypeScript, plus fewer overfetching and underfetching issues. Startup went from 15 API calls to one. Linnanen said separating remote, shared local, and component state also made the app logic easier to understand and test.
Takeaways
- Use a small proof of concept to test whether GraphQL can simplify a costly flow before committing to a migration.
- Keep highly optimized REST endpoints where they serve the product well, and define a clear path for clients to consume their data.
- Separate backend data, shared client state, and component state so each has an appropriate owner.
- Plan persistence explicitly for Apollo reactive variables; cache persistence does not persist them.
- Test Apollo local resolvers with the provider’s resolver configuration, since request mocks alone may not cover them.
Mentioned in this talk
Search inside this talk
What was claimed 14
- role atJuha Linnanen is Head of Mobile Development at Gofore
“I am Juha Linnanen from Finland, the Head of Mobile Development at Gofore”
YouTube Unverified1 source· Talk
- usesKlar app uses React Nativebuilt almost entirely in React Native
“for the past three-plus years I’ve mainly been using React Native as my tool of choice”
YouTube Verified2 sources· Talk
- uses
“The app was using Redux for state management”
YouTube Unverified1 source· Talk
- usesKlar app uses Apollo Client
“Using Apollo Client, in the end there were one or two API calls”
YouTube Unverified1 source· Talk
- usesApollo Client uses GraphQL
“Using Apollo Client, in the end there were one or two API calls”
YouTube Unverified1 source· Talk
- featureApollo Client: UseQuery, useLazyQuery, and useMutation hooks for GraphQL operations
“There are three very handy hooks available.”
YouTube Unverified1 source· Talk
- uses
“We decided to create a new back end, a CraftQL API”
YouTube Unverified1 source· Talk
- usesKlar app uses local resolvers
“we decided to try to accomplish this with local resolvers”
YouTube Unverified1 source· Talk





