Salesforce Lightning — state maintenance

Parthiban Sudhaman
incresco
Published in
3 min readFeb 12, 2018

If you are tired of finding a way to implement UI component with predictable state, you have landed in the right place.

I have put together a simple ToDo app with state maintained only in the top container component.

Poorly designed code usually takes more code to do the same things, often because the code quite literally does the same thing in several places.
― Martin Fowler

We will be building a ToDo app where you can add items, mark them as complete and undo it.

We are going to build the below components.

  1. todoAction.evt — Application event, will be fired by the child components to change the state. (Naming convention: camel casing for events)
  2. ToDoApp.app — Top level app, act as a container and most importantly maintains the state of the application. Handles the todoAction event.
  3. ToDoList.cmp — stateless component to iterate the Todo list and render ToDoItem component
  4. ToDoItem.cmp — stateless component to display each Todo item and fires application event with payload to change the state
  5. ToDoItemNew.cpm — stateless component to add new Todo item and fires application event with payload to change the state

That’s all is needed.

Let’s dive into code now.

1. todoAction.evt

<aura:event type="APPLICATION" description="todoAction">
<aura:attribute type="String" name="type"/>
<aura:attribute type="Object" name="payload"/>
</aura:event>

This application event accepts 2 params,

type: this will the type of action performed, “Example TOGGLE_COMPLETE” which will be passed by the child components when it wants to update the state.

payload: the actual payload, “Example {Id:1}”. child component will pass this params as well

2. ToDoApp.app

The top level container app and the only component which will maintain the state in this whole application.

This component will contain the child component to display the todolist, but most importantly the helper will have the actions to change the state. The current state is stored in v.state and that is one big object to have the entire state of the application.

ToDoApp.app code:

<!--
ToDoApp.app
-->

<aura:application description="ToDoApp" extends="force:slds" access="global" extensible="true">
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:handler event="c:todoAction" action="{!c.handleAction}"/>

<aura:attribute type="Object" name="state"/>
<div class="slds-page-header">
<div class="slds-media">
<div class="slds-media__body">
<h1 class="slds-page-header__title slds-truncate slds-align-middle slds-text-align_center" title="ToDo">ToDo App</h1>
</div>
</div>
</div>
<c:ToDoList state="{!v.state}" />
</aura:application>

Helper code:

/**
* ToDoAppHelper.js
*/
({
getNextState: function(prevState, action){
var nextState = prevState;

switch(action.type){
case 'GET_DEFAULT_STATE':
// Make an apex call to fetch initial data
var defaultStore =
[
{Id: 1, Item: "Complete ToDo sample", IsCompleted: true},
{Id: 2, Item: "Post in medium", IsCompleted: false}
]
nextState = defaultStore;
break;
case 'TOGGLE_COMPLETE':
nextState.map((todo, index) => {
if(todo.Id == action.payload.Id){
todo.IsCompleted = !todo.IsCompleted;
}
});
break;
case 'ADD_NEW_TODO':
const maxId = Math.max.apply(Math,nextState.map(function(item){return item.Id;}))
nextState.push({Id: maxId + 1, Item: action.payload.NewToDo, IsCompleted: false});
default:
break;
}
return nextState;
}
})

3. ToDoItem.cmp:

This is again a stateless component to render each ToDo item along with the status button of that item “Done or Not done”. Click of the button has to toggle the completion state, this happens by firing an application event with the payload (id of the item) and action as TOGGLE_COMPLETE which will be handled in the top level ToDoApp.app.

/**
* ToDoItemController.js
*/
({
toggleComplete: function(component, event){
const todoId = component.get('v.todo.Id');
const dispatch = $A.get('e.c:todoAction');
dispatch.setParam('type', 'TOGGLE_COMPLETE');
dispatch.setParam('payload', {Id: todoId});
dispatch.fire();
}
})

I hope this gives a high level understanding of one of the different ways of designing components to maintain the state from one single place.

In short,

ToDoApp — handles the application event, handles the state and host the child component

Child components — fires the application event with payload and action and is stateless

You can get the entire code base here in my GitHub link.

Inspired by Redux architecture and Jade Pennig/Adam Putinski session in Dreamforce’17.

--

--

Parthiban Sudhaman
incresco

Tech enthusiastic with a love for technology. Currently heading engineering division to convert the vision into reality @ EF, Bangalore.