React Native: A classic event model approach for the Reducer

Are you having a hard time understanding the Reducer hook? ** to be clear this is a blog non intended for beginners but for showing a different view for Reducers.

As some may remember from college(those who studied CSC or computer related stuff) the classic event model uses 3 concepts: "Events", "Handlers" and a "Monitor".

An event is a constant which describes(as detailed as possible) what happened.

A handler is a function that gets the event as a parameter to execute what would happen after the event.

The monitor is an arbitrator who chooses when the handlers show be executed according to the events. In other words, it is the one who controls the entire event system.


Whit that in mind relating to the Reducer-dispatch model is just as simple as applying what you learned to code in Java(back in school) to ReactJs or any library, API, or framework that uses this Reducer concept. 

Therefore, I decided to create my own interpretation of Reducer whenever I program in React(React-native) for this case in particular.


So basically what I did is create a reducer for a component "ImageChat" and I divided it into Events, Handlers, and Reducer(Monitor as described previously).



The Reducer:

As I mentioned before, the reducer acts like a monitor, so it takes an action, and depending on it, the monitor will execute a specific computation. In the case of ReactJs/React Native, it updates the state depending on the action that an event sent.

import Actions from "./Actions";
import {actionEventType, ImageChatState} from "./Interfaces";
import {Handlers} from "./Handlers";

function Reducer(state:ImageChatState, action:actionEventType): ImageChatState {
switch (action.type) {
case Actions.setOwnName:
return Handlers.SetOwnNameHandler(state,action.stringValue);

case Actions.setPartnerName:
return Handlers.SetPartnerNameHandler(state,action.stringValue);

case Actions.setOwnMessage:
return Handlers.SetOwnMessageHandler(state,action.stringValue);

case Actions.setPartnerMessage:
return Handlers.SetPartnerMessageHandler(state, action.stringValue);

case Actions.setMessages:
return Handlers.SetMessagesHandler(state, action.arrayValue);
}

return state;

}
export default Reducer;
The Events:

So this section is interesting, because for most ReactJs developers, which have been dealing with redux and similar stuff, you would tell me that this is the thing that usually goes in a dispatch function and well it is. The difference here is that the code is more manageable and readable. If a new programmer edited the code or added a new Action to he reducer envieronment , it must create a new Event. 
Also, events are basically objects which contain an action and parameters for executing a handlers, as you could see in the static methods of the ImageEvents class:
import Actions from "./Actions";
import {actionEventType} from "./Interfaces";

class ImageEvents {
public static GetEventForSetMessages(messagesArray:string[]):actionEventType {
return {type:Actions.setMessages, arrayValue:messagesArray}
}
public static GetEventForSetPartnerMessage(value:string){
return {type:Actions.setPartnerMessage,stringValue:value};
}
public static GetEventForSetOwnMessage(value:string){
return {type:Actions.setOwnMessage, stringValue:value}
}
public static GetEventForEmptyOwnMessage(){
return {type:Actions.setOwnMessage, stringValue:""}
}
public static GetEventForSetPartnerName(value:string){
return {type:Actions.setPartnerName,stringValue:value}
}
public static GetEventForSetOwnName(value:string){
return {type:Actions.setOwnName, stringValue:value}
}

}

export default ImageEvents;

The Handlers:
Handlers in this case help in two ways to our code: By extracting the complexity in a new class we can have as much detail in a method and reflect one line in the Reducer.
import {ImageChatState} from "./Interfaces";

export class Handlers {
public static SetOwnNameHandler(
state:ImageChatState,
value:string|undefined)
:ImageChatState {
if(value === undefined)
return {...state};
return {
...state,
ownName:value
}
}

public static SetPartnerNameHandler(
state:ImageChatState,
value:string|undefined)
:ImageChatState {
if(value === undefined)
return {...state};
return {
...state,
partnerName:value
}
}

public static SetOwnMessageHandler(
state:ImageChatState,
value:string|undefined)
:ImageChatState {
if(value === undefined)
return {...state};
return {
...state,
ownMessage: value
}
}

public static SetPartnerMessageHandler(
state:ImageChatState,
value:string|undefined)
:ImageChatState {
if(value === undefined)
return {...state};
return {
...state,
partnerMessage: value
};
}

public static SetMessagesHandler(
state:ImageChatState,
value:string[]| undefined)
:ImageChatState{

if(value === undefined)
return {...state};

return {
...state,
messages: [...value]
};
}
}


Comments

Popular posts from this blog

Analysis of dark patterns in League of Legends and Star Wars:Battlefront II with the usage of Loot Boxes

Kerstin's Fate developer diary

Exploring LLMs with Ollama and Llama3