Skip to main content

[ Part 3 ] First Async call, redux-thunk


Previous Part (adding redux): http://dev.basharallabadi.com/2018/09/part-2-nutracker-reactjs-application.html

By default the store only understands object dispatched actions, i.e. it won't support async calls out of the box neither functions, which conflicts with our need to call an api asynchronously and get the results and returns those results to our reducers to update the state.


Redux Thunk

The simplest approach to achieve what we need is to use something called middleware in redux that can pre process our actions and then proceed to the store when it's done.
Redux thunk is a middleware library that knows how to handle a function received as a dispatched action from a component then based on the result it can dispatch more actions to the store to notify our reducers with the results.
mainly we use it to process async calls and based on the result (success/fail) we ask it to dispatch the proper actions when.

First lets update our foodRepo to actually call an api:
- install corss-fetch npm install --save cross-fetch to use the fetch API and get promises for our async calls.
- renamed the mock method in foodRepo to findFoodMock(), and created new one for the real call which does a fetch call to our api and parse the json body.
- I added this in the package.json: `proxy": "http://localhost:8080` to avoid Cross origin errors so react will proxy requests to this server through the development server.

findFood(name) {
return fetch(`/api/food/search?name=${name}`)
.then(response => response.json());
}

Actions Change

was:

export const SEARCH_FOOD = 'SEARCH_FOOD';
export function searchFood(term) {
 console.log(`in searchFood ${term}`);
 return {
  type: SEARCH_FOOD,
  term
 }
}
Let's change our actions to make an async call, we need two actions  :
- one to declare the call has started (so components can render loading spinner for example)
- another one to handle the result of the call
we already have SEARCH_FOOD action but now, it will now be used to:
- notify the reducers that the call started instead
to send the ajax call we will introduce a new function (fetchFood) that will:
- invoke the ajax call and host the logic to handle the promise result
- dispatch SEARCH_FOOD
the way we will handle the ajax call result is by dispatching a new action with the result as payload:
 RECEIVE_SEARCH_FOOD_RESULTS
after changes:

Reducers

modifed my reducers as well:
- if the action is SEARCH_FOOD it will set a flag that we are fetching data
- if the action is RECEIVE_SEARCH_FOOD_RESULTS, we will handle the results for that term, and update the state with the results array and unset the fetching flag.

what changes on the component side?

Previously in FoodSearch.js we dispatched the searchFood() action creator result (what builds SEARCH_FOOD action payload )
- the dispatch(searchFood(term)) will change now to dispatch(fetchFood(term))
- this new action creator returns a function that takes dispatch as parameter (to use it later on)

but as we said earlier: the store doesn't understand function actions by default and if you run the app now you will get this error message
Error: Actions must be plain objects. Use custom middleware for async actions.
so we will:
- install redux-thunk run npm install --save redux-thunk
- modify our store creation logic:
import thunkMiddleware from 'redux-thunk';
// lines omitted...
const store = createStore(rootReducer, applyMiddleware(thunkMiddleware));
- running the code will show results from server.

Source for day 3: https://github.com/blabadi/react-nutracker/tree/day3/async-api-call
references: https://redux.js.org/advanced/asyncactions

Comments

Popular posts from this blog

Android RecyclerView - Adding Empty View

So RecyclerView was introduced to replace List view and it's optimized to reuse existing views and so it's faster and more efficient as stated in the documentation:

https://developer.android.com/training/material/lists-cards.html

While using it, I faced the issue of missing a useful functionality that is implemented in ListView.
that feature is setting an empty view in case there was no records.

In ListView it was as simple as this

View emptyView = findViewById(R.id.mylist_empty_view);
ListView  myList = ....
myList.setEmptyView(emptyView);

but this method doesn't exist for recycler view so we need a work around until android team fixes this.


and here are the screen shots of both list view and recycler view fix

List view :

Recycler view :



here is how I fixed it:



here is the content of empty_view, it can be anything.



Enjoy.

Creating your own OAuth2 server and clients using spring security - part 1

In this series of posts, I'll try to put together a simple working example on how to create your own OAuth2 server.

if you want to know more on OAuth2 and when to use it as authentication and authorization protocol then you can search about it on google and i'll put some URLs later.

Now I assume you are familiar with java web applications using Spring and maven.

to get started we need to create the server side with all dependencies required and i'll list them here, i'll use maven 2 to ease downloading dependencies for us.


Steps:

1- Create new maven project with arch type webapp:



2- Add the required depenedencies for spring, spring security, spring-oauth2, hibernate & other libraries (required for this tutorial only you can use other libraries if you like)

https://gist.github.com/anonymous/d33a31ddc3ba84375cf3

3- I used hibernate to automate the creation of the schema required by spring OAuth2 to manage tokens (it's required to have schema created in db if you a…

Android - Multiple themes for one application

Sometimes you want to have multiple themes for your app
one strong example is having the ability to switch between dark and light themes because during night, a white bright screen can really be annoying for users eyes

Android will do most of the work for you but it may be required to change icons between themes to fit colors
In this blog I'll show a simple app with both dark and light themes and how to change icons without having to do that from code and keep things clean and centralized.
first of all let's create our activity, it will look something like this :


In /rest/values/styles.xml, we inherit Theme.AppCompat
 <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="Theme.AppCompat">
        <!--
            Theme customizations available in newer API levels can go in
            res/values…