We are gonna explain how redux middleware work, then use redux thunk.
So before doing any code, how does redux middleware works?
Redux middleware is how you would handle asynchronous operations. Since redux operates synchronously, you would need middleware to handle asynchronous operations since you would handling promises, callbacks and async and await. We will create a react native and react app.
First create a react-native app, then a react app.
react-native init starwarsApiAppAND
npx create-react-app star-wars-api-app
Then cd to first the react-native directory since we are working on that first, and install these dependencies, then afterward do the same thing for your react app.
npm i redux-thunk redux react-redux axios superagent
In both apps create a redux folder, and have a reducer file and store file.
touch reducer.js store.js
Now we will first define our initialState will have a loading, which will indicate if our reducer is done fetching, a people array which will take the data, and an errorMessage for catching errors. Define our reducer in our reducer file.
Our action types are.
GET_PEOPLE_PENDING ← which will indicate if it is fetching data.
GET_PEOPLE_FULFILLED ← Indicate the fetching of data is successful.
GET_PEOPLE_REJECTED ← For catching errors.
Based on the GET_PEOPLE_PENDING action type. We will set our loading to true, which means it is getting data. Based on the GET_PEOPLE_FULFILLED action type we will set the data to our people array, and loading to false. Then based on the GET_PEOPLE_REJECTED we will set our errorMessage catching any errors.
Now we will define our action creators which will return the types we defined earlier. Now we will define our fetchData action creator which will take bool as an argument. Will return a loading state to true. Indicating we are the middle fetching data. Define it in both your react-native and react app.
Then define your fetchData fulfilled that will set your loading to false indicating we are done fetching data, and set our people array to data.
Then we will define our fetchDataRejected action creator which handles error by setting our errorMessage to the error, and loading to false.
Now all of our action creators are defined. Let go to our store.js file where will define our middleware. We will first import createStore, applyMiddleware from redux. Then import reducer from reducer. Then import your action creators from the reducer.js file as named exports, thunk as a default export from redux-thunk for handling asynchronous operations, and axios and superagent for getting that data.
Now we will define our getPeople method that will handle getting data. We will use async/await, axios then superagent.
Here is the async/await way.
We are returning a callback that is asynchronous using the async keyword, and then we are getting the data via fetch which is similar to axios, in that it uses promises. Then we are dispatching the fetchData and set our loading state to true. Then we are getting the data by the json() method since the data returned is json. Then we are dispatch fetchDataFulfilled with people results as arguments. All within a try/catch block for catching errors.
Now we will use axios.
We will dispatch the fetchData action creator before getting to the data to indicate we are getting data. Once it is resolved or rejected we will set the loading state to false.
Now we will use superagent.
We will first indicate that we are fetching data. Then we will use the get method in which we will pass the url, and chain the end method which will set our people array.
Now we have our asynchronous operations setup. We will start setting up the UI.
In this case we will define our index.js file in our react app, first we will import our Provider, and store from react-redux and store.js file. Also comment out your register worker.
Now since our react app is configured, lets configure our react-native app, by the app.js file. We will import provider, store, and have our app return the provider nesting the PeopleList (which will define later).
Now we will define our app.js in our react app, which will just render our PeopleList component.
And copy and paste this in your App.css file, which is the same styles as your react-native app.
Now we will define our peopleList which will use to get people from api call. We will import the PureComponent which will allow shallow comparison of state and props. Then connect method responsible for connecting your component to store, your action creator from your store, and the UI from react-native.
Then we will declare our component as a class component, and right below the declaration. Define your styles like we did in our react app, map your redux state to props, your dispatchers to props, and connect your component to store.
Now with our state and dispatcher to props. In our componentDidMount we will fetch the data.
Then in our render method we will destruct our loading and people from our redux state, and if the loading is false render the people or return Loading……
Now it should render our react-native app with our people.
Now we will define our react app the same unless we will not import the UI from react-native for the react app.
Now it should render our react app.
Now that is how we call asynchronous operations using redux-thunk. Play with it try using Promise.all for handling multiple promises. Don’t worry about your program crashing when learning, instead play with it, see what you can do.
Here is my github for reference and happy coding!