Monday, December 6Digital Marketing Journals

Expo, React native… onboarding chatbot: Part three | by Rinaldo Stevenazzi | Nov, 2021


In summary for the moment we have, bubbles for the chatbot and the user, animation to simulate the chatbot’s text input.
We still have to link all these components together, make them communicate.

React allows us to create contexts, to encapsulate a part of our components to make them communicate with each other.
We will share in this context a very usefull react hook : UseReducer. This hook will allow us to manage complex state logic.
Then we will modified the chatbot screen and the bubbles factory to use the state management thought his context and update the app.

Let’s start by create and initialise a UseReducer.

const [state, dispatch] = useReducer(ChatBotReducer, InitialChatBotState)

UseReducer takes 2 arguments :

  • a reducer function (ChatBotReducer),
  • initial state as input (InitialChatBotState),

This hooks will returns the current state and a dispatch function as output with array destructuring.

Too well understand the redux logic, let’s start to talk about state.

UseReducer is the state management solution.

A state is immutable. It is a picture taken at a given moment. For example our this is our initial State :

export const InitialChatBotState = {
currentAction: ChatBotStates.STATE_ONE,
renderItem: RenderItems.CHAT_BUBBLE,
showButton: false,
nextAction: ChatBotStates.STATE_TWO
}

It is a object with specific properties who describe our statement.

The render item used for this state will be chat-bubble , no button and the currentAction is State One for example !

Now, we have to determine, analyse the Figma board created by the UI / UX team :

Let’s describe what we have :

  • the chatbot start to write, chatbot bubbles start to be visible.
  • at the end typing a button is showing,
  • Click on the button (here, purple arrows are actions in figma board) and show a user bubble,

the first bullet is is exactly our initialState ! that’s good !

For this article part, we won’t follow the board figma above. We will make 2 states in addition to the initial one and put them in a enumeration object :

export const ChatBotStates = Object.freeze({
STATE_ONE: 'stateOne',
STATE_TWO: 'stateTwo',
STATE_THREE: 'stateThree'
})

1. How Conversational AI can Automate Customer Service

2. Automated vs Live Chats: What will the Future of Customer Service Look Like?

3. Chatbots As Medical Assistants In COVID-19 Pandemic

4. Chatbot Vs. Intelligent Virtual Assistant — What’s the difference & Why Care?

The first argument to create a useReducer is reducer (also called a reducing function). this function will manage and centralised all those states.
Reducers calculate a new state based on the previous state and an action.

export const ChatBotReducer = (state, action) => {
switch (action.type) {
case ChatBotStates.STATE_ONE :
return {
currentAction: action.type,
renderItem: RenderItems.CHAT_BUBBLE,
showButton: false,
showModal: false,
nextAction: ChatBotStates.STATE_TWO
}
case ChatBotStates.STATE_TWO :
return {
currentAction: action.type,
renderItem: RenderItems.USER_BUBBLE,
showButton: true,
showModal: false,
nextAction: ChatBotStates.STATE_THREE
}
case ChatBotStates.STATE_THREE :
return {
currentAction: action.type,
renderItem: RenderItems.CHAT_BUBBLE,
showButton: false,
showModal: false,
nextAction: null
}
}
}

This is our reducer called, ChatBotReducer. We find here our 2 new states, with their own particularities. let’s dive in this reducer function.

A reducer is a function with 2 arguments :

  • State which is the current state with all properties (currentAction, renderItem, etc.).
  • An action is a plain object that represents an intention to change the state. Actions are the only way to get data into the store. Those actions will be dispatched by the dispatch function

We use a conditional switch / case statement to manage the states in relation to the received action.

To create our chatbot context we use createContext method form react library. this method have argument, the defaultValue, is usefull when we dont have a provider, but, in our case we will create a provider with a useReducer as value, so we set defaultValue to undefined.

const ChatBotContext = createContext(undefined)

export default ChatBotContext

export function ChatBotProvider ({ children }) {
const [state, dispatch] = useReducer(ChatBotReducer, InitialChatBotState)
const reducer = { dispatch, state, ChatBotStates }

return (
<ChatBotContext.Provider value={{ reducer }}>
{children}
</ChatBotContext.Provider>
)
}

We will use our context in a component, ChatBotProvider. This component is a wrapper, as AnimatedWrapper for the chat-typing component.

Every Context object comes with a Provider that allows consuming components to subscribe to context changes.
Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider.

As you can see, we use the userReducer inside our ChatBotProvider.

Next, we create a reducer object that includes the dispatch function, the state from the initialisation of useReducer and the list of all states. We pass this reducer object to the props value of the provider.

This way we share all the tools used to communicate between all components, chat-bubble, user-bubble, bubbles-factory, etc. Chat bot state will be available for each component wrapped in our provider.

Leave a Reply