The following article is part of a series of articles about our NerdWallet Summer Internship program. Ming Horn is a student at Mills College and shared their experience as an software engineer intern. If you are curious about joining NerdWallet as an intern or full-time employee, please apply for one of our open positions!
This summer, I’ve worked as a software engineering intern at NerdWallet. I was part of the Mobile Core team, which helps build out the ‘core’ of the NerdWallet mobile app and support mobile feature engineers. My main project was working on writing Apollo GraphQL schema and migrating several screens from Redux to Apollo GraphQL.
Here are some of my tips and learnings about migrating to Apollo GraphQL.
In Redux, events in the view dispatch actions. The store dispatcher handles the actions and combines data from the API and current stored state through reducers to calculate the updated state that the view needs.
In GraphQL the view makes queries or mutations which the Apollo Client (or any other GraphQL client) then parses and checks if the data already exists in the cache. If not, it makes a request to the Apollo Server, the schema maps the query to its resolvers, which request data from the APIs and returns it in the shape dictated by the schema. The request then resolves and the returned data is stored in the cache for future use and the data is returned to the view.
- Actions = queries, mutations, or subscriptions from client
- Selectors = query resolvers
- Reducers = mutation resolvers
- Store State = Apollo cache
Disclaimer: I am assuming you know some basics about Apollo GraphQL and Redux, and have set up your Apollo Server and Apollo Client provider in your app. There are a myriad of other articles about how to do that.
Step 1: Identify the most commonly used data in your apps
This is what you want to migrate first: for example, I migrated the
globalProfile which encompasses data like your
I would recommend choosing some basic foundational types before higher-order types. Types that have one or two levels of nesting typically are the right ones to choose.
Step 2: Examine how the client uses the data and what it really needs
Look at a screen that uses the data that you identified in the first step. Start by inspecting the selectors it uses. What other data does it need? Can most of it come from one data source?
Let’s say you have a component connected to state below:
So you would want to write a
getDisplayableFeed query, and if
getUserLastName come from the
globalProfile, you would want to write a
Step 3: Write GraphQL schema and resolvers
Now that you know what data you need to fetch and how it should render you can write the schema. Here you’ll define the different data types — these are basically models; typically they’re organized based on how you will make a request. Then you define queries and mutations based on what you learned in Step 2. For example:
Resolvers are what actually fetch data for the queries, mutations, and types. There are lots of great articles about how to write them efficiently so that the number of server requests to APIs are minimized.
Step 4: Make your first query!
Sometimes there’s more complex situations when migrating…
There were two main issues I ran into migrating an app implemented with Redux to GraphQL. One, I didn’t write schema for every piece of data loaded by a screen so some still needed to come from the Redux store. Two, components rendering data loaded from the Redux store expect to have it all immediately without a loading state.
Additionally simply wrapping the component in a
Query component seemed a little awkward or impossible if there were more HOCs that did anything remotely complex like dynamically render form fields based on the Redux state.
The solution was a HOC! I created a
withApolloQuery HOC that wrapped the container in a
Query component. I could then just write:
Thanks to the Mobile Core team: Casey, Steve, Martin, Rahat, Eric, and Sam, for an amazing summer, I had a great time being your Nerdling!