Todos - Async

Let's add some asynchronous calls to the previous Todos example

Introduction

State management usually gets very complicated when we need to build a realistic app, that for instance needs to make calls to a server API, therefore it needs to integrate the state with asynchronous calls. For this example we will use Conan's autoBind feature, which is fully described under Conan asynchronous stateโ€‹

Adding async calls

Let's say our Todo app needs to make an API call to fetch the current todos, and to add and toggle a todo. We could easily think of embedding that logic in its own service class. We could model that as:

Js
Ts
Js
export class TodoListServiceImpl {
fetch() {
return Asaps.delayed([{ description: 'test', id: '-1', status: ToDoStatus.PENDING }], 500, 'fetch');
}
addTodo(todo) {
return Asaps.delayed(todo, 5000, 'addTodo');
}
toggleTodo(todo) {
return Asaps.delayed(todo, 1000, 'toggleTodo');
}
}
Ts
export interface TodoListService {
fetch(): Asap<ToDo[]>;
โ€‹
addTodo(todo: ToDo): Asap<ToDo>;
โ€‹
toggleTodo(todo: ToDo): Asap<ToDo>;
}
โ€‹
export class TodoListServiceImpl implements TodoListService {
public fetch(): Asap<ToDo[]> {
return Asaps.delayed([{description: 'test', id: '-1', status: ToDoStatus.PENDING}], 500, 'fetch');
}
โ€‹
public addTodo(todo: ToDo): Asap<ToDo> {
return Asaps.delayed(todo, 5000, 'addTodo');
}
โ€‹
public toggleTodo(todo: ToDo): Asap<ToDo> {
return Asaps.delayed(todo, 1000, 'toggleTodo');
}
}

We are just simulating the API calls with a delayed Asap

Note the function names match the reducers names, therefore ConanJs will bind each funcrion with its corresponding reducer

Creating the state

As mentioned above we will be using autoBind, passing the todoListSevice implementation:

Js
Ts
Js
export class TodoListAsyncStateFactory {
static create(todoListService) {
return Conan.state({
name: 'todos-async',
initialData: {
appliedFilter: VisibilityFilters.SHOW_ALL,
todos: []
},
reducers: TodoListReducersFn,
autoBind: todoListService
});
}
}
Ts
export class TodoListAsyncStateFactory {
static create(todoListService: TodoListService): TodoListState {
return Conan.state<TodoListData, TodoListReducers>({
name: 'todos-async',
initialData: {
appliedFilter: VisibilityFilters.SHOW_ALL,
todos: []
},
reducers: TodoListReducersFn,
autoBind: todoListService
})
}
}

As in the Todos example, Conan's DI will hold the definition of the state, but in this example it will instantiate the async one we have just described.

Js
Ts
Js
export let diContext = DiContextFactory.createContext({
todoListState: TodoListAsyncStateFactory.create,
}, {
todoListService: TodoListServiceImpl
});
Ts
export let diContext = DiContextFactory.createContext<App, InternalDependencies>({
todoListState: TodoListAsyncStateFactory.create,
}, {
todoListService: TodoListServiceImpl
},
);

This is all that is needed to bring asynchronous behaviour into ConanJs's state, the rest of the code is the same as the simple Todos example.

โ€‹

Getting the code

Please feel free to download the example at:

or just play with it in the code sandbox.

Code sandbox

TODOs with async actions

โ€‹

โ€‹

โ€‹