Reactive Side Effects of Actions in Loklak Search

In a Redux based application, every component of the application is state driven. Redux based applications manage state in a predictable way, using a centralized Store, and Reducers to manipulate various aspects of the state. Each reducer controls a specific part of the state and this allows us to write the code which is testable, and state is shared between the components in a stable way, ie. there are no undesired mutations to the state from any components. This undesired mutation of the shared state is prevented by using a set of predefined functions called reducers which are central to the system and updates the state in a predictable way.

These reducers to update the state require some sort triggers to run. This blog post concentrates on these triggers, and how in turn these triggers get chained to form a Reactive Chaining of events which occur in a predictable way, and how this technique is used in latest application structure of Loklak Search. In any state based asynchronous application, like, Loklak Search the main issue with state management is to handle the asynchronous action streams in a predictable manner and to chain asynchronous events one after the other.  The technique of reactive action chaining solves the problem of dealing with asynchronous data streams in a predictable and manageable manner.

Overview

Actions are the triggers for the reducers, each redux action consists of a type and an optional payload. Type of the action is like its ID which should be purposely unique in the application. Each reducer function takes the current state which it controls and action which is dispatched. The reducer decides whether it needs to react to that action or not. If the user reacts to the action, it modifies the state according to the action payload and returns the modified state, else, it returns the original state. So at the core, the actions are like the triggers in the application, which make one or more reducers to work. This is the basic architecture of any redux application. The actions are the triggers and reducers are the state maintainers and modifiers. The only way to modify the state is via a reducer, and a reducer only runs when a corresponding action is dispatched.

Now, who dispatches these actions? This question is very important. The Actions can be technically dispatched from anywhere in the application, from components, from services, from directives, from pipes etc. But we almost in every situation will always want the action to be dispatched by the component. Component who wishes to modify the state dispatch the corresponding actions.

Reactive Effects

If the components are the one who dispatch the action, which triggers a reducer function which modifies the state, then what are these effects, cause the cycle of events seem pretty much complete. The Effects are the Side Effects, of a particular action. The term “side effect” means these are the piece of code which runs whenever an action is dispatched. Don’t confuse them with the reducer functions, effects are not same as the reducer functions as they are not associated with any state i.e. they don’t modify any state. They are the independent sources of other actions. What this means is whenever an Action is dispatched, and we want to dispatch some other action, maybe immediately or asynchronously, we use these side effects. So in a nutshell, effects are the piece of code which reacts to a particular action, and eventually dispatches some other actions.

The most common use case of effects is to call a corresponding service and fetch the data from the server, and then when the data is loaded, dispatch a SearchCompleteAction. These are the simplest of use cases of effects and are most commonly use in Loklak Search. This piece of code below shows how it is done.

@Effect()
search$: Observable<Action>
= this.actions$
.ofType(apiAction.ActionTypes.SEARCH)
.map((action: apiAction.SearchAction) => action.payload)
.switchMap(query => {
return this.apiSearchService.fetchQuery(query)
.map(response => new apiAction.SearchCompleteSuccessAction(response))

This is a very simple type of an effect, it filters out all the actions and react to only the type of action which we are interested in, here SEARCH, and then after calling the respective Service, it either dispatches SearchComplete or a SearchFail action depending on the status of the response from the API. The effect runs on SEARCH action and eventually dispatches, the success or the fail actions.

This scheme illustrates the effect as another point apart from components, to dispatch some action. The difference being, components dispatch action on the basis of the User inputs and events, whereas Effects dispatch actions on the basis of other actions.

Reactive Chaining of Actions

We can thus take the advantage of this approach in a form of reactive chaining of actions. This reactive chaining of actions means that some component dispatches some action, which as a side effects, dispatches some other action, and it dispatches another set of actions and so on. This means a single action dispatched from a component, brings about the series of actions which follow one another. This approach makes it possible to write reducers at the granular level rather than complete state level. As a series of actions can be set up which, start from a fine grain, and reaches out to a coarse grain. The loklak search application uses this technique to update the state of query. The reducers in the loklak search rather than updating the whole query structure update only the required part of the state. This helps in code maintainability as the one type of query attribute has no effect on the other type

@Effect()
inputChange$: Observable<Action>
= this.actions$
.ofType(queryAction.ActionTypes.VALUE_CHANGE)
.map(_ => new queryAction.QueryChangeAction(''));

@Effect()
filterChange$: Observable<Action>
= this.actions$
.ofType(queryAction.ActionTypes.FILTER_CHANGE)
.map(_ => new queryAction.QueryChangeAction(''));

Here the QUERY_CHANGE action further can do other processing of the query and then dispatch the SearchAction, which eventually calls the service and then return the response, then the success or fail actions can be dispatched eventually.

Conclusion

The reactive side effects is one of the most beautiful thing we can do with Redux and Reactive Programming. They provide an easy clean way to chain events in an application, which helps in a cleaner non-overlapping state management along with clean and simple reducers. This idea of the reactive chaining can be extended to any level of sophistication, and that too in a simple and easy to understand manner.

Resources and links

Continue Reading

Use of Flux Architecture to Switch between Themes in SUSI Web Chat

While we were developing the SUSI Web Chat we got a requirement to build a dark theme. And to build a way that user can switch between dark and light theme.

SUSI Web Chat application is made according to the Flux architecture, So we had to build sub components according to that architecture.

What is flux:

Flux is not a framework. It is an Architecture/pattern that we can use to build applications using react and some other frameworks. Below figure shows the way how that architecture works and how it communicate.

How flux works:

Flux has four types of components. Those are views, actions, dispatcher and stores. We use JSX to build and integrate views into our JavaScript code.

When someone triggers an event from view, it triggers an action and that action sends particular action details  such as Actiontype, action name  and data to dispatcher. Dispatcher broadcasts those details to every store which are registered with the particular dispatcher. That means every store gets all the action details and data which are broadcasting from dispatchers which they are registered.

Let’s say we have triggered an action from view that is going to change the value of the store. Those action details are coming to dispatcher. Then dispatcher broadcasts those data to every store that registered with it. Matching action will trigger and update its value. If there is any change happened in store, view automatically updates corresponding view.

How themes are changing:

We have a store called “SettingStore.js”. This “SettingStore” contains theme values like current theme. We store other settings of the application such as: Mic input settings, Custom server details, Speech Output details, Default Language, etc.it is responsible to provide these details to corresponding view.

let CHANGE_EVENT = 'change';
class SettingStore extends EventEmitter {
   constructor() {
       super();
       this.theme = true; 
   }

We use “this.theme = true” in constructor to switch light theme as the default theme.

getTheme() { //provides current value of theme
       return this.theme;
   }

This method returns the value of the current theme when it triggers.

   changeTheme(themeChanges) {
       this.theme = !this.theme;
       this.emit(CHANGE_EVENT);
   }

We use “changeTheme” method to change the selected theme.

   handleActions(action) {
       switch (action.type) {
           case ActionTypes.THEME_CHANGED: {
               this.changeTheme(action.theme);
               break;
           }
           default: {
               // do nothing
           }
       }
   }
}

This switch case is the place that store gets actions distributed from the dispatcher and executes relevant method.

const settingStore = new SettingStore();
ChatAppDispatcher.register(settingStore.handleActions.bind(settingStore));
export default settingStore;

Here we registered our store(SettingStore) to “ChatAppDispatcher” .

This is how Store works.
Now we need to get the default light theme to the view. For that we have to call ”getTheme()” function. We can use the value it returns to update the state of the application.
Now we are going to change the theme. To do that we have to trigger “changeTheme” method of “Settingstrore” from view ( MessageSection.react.js ).
We trigger below method on click of the “Change Theme” button. It triggers the action called “themeChanged”.

 themeChanger(event) {
   Actions.themeChanged(!this.state.darkTheme);
 }

Previous method executes “themeChanged()” function of the actions.js file.

export function themeChanged(theme) {
 ChatAppDispatcher.dispatch({
   type: ActionTypes.THEME_CHANGED,
   theme //data came from parameter
 });
};

In above function we collect data from the view and send those data, method details to dispatcher.
Dispatcher sends those details to each and every registered store. In our case we have “SettingStore” and update the state to new dark theme.
This is how themes are changing in SUSI AI Web Chat application. Check this link to see the preview.

Resources:

  • Read About Flux: https://facebook.github.io/flux/
  • GitHub repository: https://github.com/fossasia/chat.susi.ai
  • Live Web Chat: http://chat.susi.ai/
Continue Reading

Shifting from Java to Kotlin in SUSI Android

SUSI Android (https://github.com/fossasia/susi_android) is written in Java. After the announcement of Google to officially support Kotlin as a first class language for Android development we decided to shift to Kotlin as it is more robust and code friendly than Java.

Advantages of Kotlin over Java

  1. Kotlin is a null safe language. It changes all the instances used in the code to non nullable type thus it ensures that the developer don’t get any nullPointerException.
  2. Kotlin provides the way to declare Extensive function similar to that of C#. We can use this function in the same way as we use the member functions of our class.
  3. Kotlin also provides support for Lambda function and other high order functions.

For more details refer to this link.

After seeing the above points it is now clear that Kotlin is much more effective than Java and there is harm in switching the code from Java to Kotlin. Lets now see the implementation in Susi Android.

Implementation in Susi Android

In the Susi Android App we are implementing the MVP design with Kotlin. We are converting the code by one activity each time from java to Kotlin. The advantage here with Kotlin is that it is totally compatible with java at any time. Thus allowing the developer to change the code bit by bit instead of all at once.Let’s now look at SignUp Activity implementation in Susi Android.

The SignUpView interface contains all the function related to the view.

interface ISignUpView {


  fun alertSuccess()

  fun alertFailure()

  fun alertError(message: String)

  fun setErrorEmail()

  fun setErrorPass()

  fun setErrorConpass(msg: String)

  fun setErrorUrl()

  fun enableSignUp(bool: Boolean)

  fun clearField()

  fun showProgress()

  fun hideProgress()

  fun passwordInvalid()

  fun emptyEmailError()

  fun emptyPasswordError()

  fun emptyConPassError()


}

The SignUpActivity implements the view interface in the following way. The view is responsible for all the interaction of user with the UI elements of the app. It does not contain any business logic related to the app.

class SignUpActivity : AppCompatActivity(), ISignUpView {


  var signUpPresenter: ISignUpPresenter? = null

  var progressDialog: ProgressDialog? = null


  override fun onCreate(savedInstanceState: Bundle?) {

      super.onCreate(savedInstanceState)

      setContentView(R.layout.activity_sign_up)

      addListeners()

      setupPasswordWatcher()


      progressDialog = ProgressDialog([email protected])

      progressDialog?.setCancelable(false)

      progressDialog?.setMessage(this.getString(R.string.signing_up))


      signUpPresenter = SignUpPresenter()

      signUpPresenter?.onAttach(this)

  }


  fun addListeners() {

      showURL()

      hideURL()

      signUp()

  }


  override fun onOptionsItemSelected(item: MenuItem): Boolean {

      if (item.itemId == android.R.id.home) {

          finish()

          return true

      }

      return super.onOptionsItemSelected(item)

  }

Now we will see the implementation of models in Susi Android in Kotlin and compare it with Java.

Lets First see the implementation in Java

public class WebSearchModel extends RealmObject {

  private String url;

  private String headline;

  private String body;

  private String imageURL;


  public WebSearchModel() {

  }


  public WebSearchModel(String url, String headline, String body, String imageUrl) {

      this.url = url;

      this.headline = headline;

      this.body = body;

      this.imageURL = imageUrl;

  }


  public void setUrl(String url) {

      this.url = url;

  }


  public void setHeadline(String headline) {

      this.headline = headline;

  }


  public void setBody(String body) {

      this.body = body;

  }


  public void setImageURL(String imageURL) {

      this.imageURL = imageURL;

  }


  public String getUrl() {

      return url;

  }


  public String getHeadline() {

      return headline;

  }


  public String getBody() {

      return body;

  }


  public String getImageURL() {

      return imageURL;

  }

}
open class WebSearchModel : RealmObject {


  var url: String? = null


  var headline: String? = null


  var body: String? = null


  var imageURL: String? = null


  constructor() {}


  constructor(url: String, headline: String, body: String, imageUrl: String) {

      this.url = url

      this.headline = headline

      this.body = body

      this.imageURL = imageUrl

  }

}

You can yourself see the difference and how easily with the help of Kotlin we can reduce the code drastically.

For diving more into the code, we can refer to the GitHub repo of Susi Android (https://github.com/fossasia/susi_android).

Resources

Continue Reading
Close Menu