This layer makes network calls and returns the response. It contains no logic whatsoever.
Description - Why do we abstract networking?
One thing I've seen in a lot of apps is how much the networking layer "bleeds" into the rest of the app. When we don't abstract our networking layer, mocking out our networking layer for tests or local development becomes difficult. I like to keep my networking code completely decoupled from the rest of the app and injected as a dependency abstracted by an interface (this is the dependency inversion principle). Let's go over an example
Let's build an app that can take a zip code, or the user's current location from the browser, and display the temperature for that location. We'll use Open Weather for this, and start with the current weather call.
The response object is has a dictionary called
main that includes a
temp in Kelvin, and a property called
name with the name of the location.
We want to decouple ourselves from the actual API calls and translate this into the model our app uses so that we can break our app into differen slices and
be able to easily write tests, quickly switch to a local mock network, or decouple our UI/the rest of the app from a networker if using a tool like Storybook.
The first thing I like to do is set up a Promise type with the data we expect back from an API response. This is essentially a subset of what axios provides, but I abstract it so that 1) I'm not bleeding my networking library (Axios) into the rest of the app and 2) I can swap axios for something different if I ever need to, and I only would need to update the types here.
Of all the things in the Axios response, I really only care about the data and status, so I'm going to make an interface based on that.
While this type is nice, all of our network responses will be of type
Promise<NetworkResponse<T>>. So to simplify this a bit, I'll create another type that combines
If this is confusing, hopefully it'll get a bit clearer when we define our first network call!
Say we'd like to make a call to Open Weather to get some weather data. Our app is going to display the current temperature for a zip code. Based on the response JSON, we can create a type in our app that matches the response like this:
We probably also will want a type check to make sure the data is in the format we expect. This would look like this
The purpose of the type check on the response is to verify the response is in the format we expect. Our app will have issues if we've named a property incorrectly or expected a string when we got a number.
Let's create an interface for our networking layer to conform to in order to get this current weather response. We know the API takes a zip code and get the current weather, so it should look like this
I use axios on my web projects, but the beauty of this pattern is you can use whatever you want since it's all encapsulated in one file! Create these network requests however best suits you
We also know that we're going to get weather for a location, so we can set that up now as well based on the Open Weather API. Note
params here correlate directly to the Open Weather API.
And we will fill in the rest of the networker
Next we'll move onto a data transformer to type check and translate our response into what the app will use!