SlideShare una empresa de Scribd logo
1 de 55
Descargar para leer sin conexión
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 1/55
EFFECTIVE
APPLICATION STATE
MANAGEMENT
Oliver Hager - Dextra 🤘
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 2/55
O que é o estado de aplicação?
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 3/55
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 4/55
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 5/55
LIÇÃO 1
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 6/55
BAD 💩
render(){
return (
this.state.userRole === 'admin' ?
<AdminComponent/> :
<UserComponent/>
)
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 7/55
GOOD 👍
render(){
return (
this.state.userIsAdmin ?
<AdminComponent/> :
<UserComponent/>
)
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 8/55
render(){
function calculateTotalCost(items){
return items.reduce(
(p,item) => p+(item.price*item.quantity), 0.0
).toFixed(2);
}
return (
<div>
<CartItemList items={this.state.cartItems}/>
<div className='cart-total'>{
calculateTotalCost(this.state.cartItems) + '$'
}<div/>
<div/>
)
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 9/55
⭐ Mantenha mais simples possível, p.e. booleano
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 10/55
LIÇÃO 2
Compose your state
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 11/55
TRIVIAL 👍
const update = (state, newState) => Object.assign({}, state, newState);
const updateState = (state, newState) => ({ ...state, ...newState }); //
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 12/55
ASSIGN/... VS MERGE
New Repl ohagermy repls community
BETA
DevCamp2017: Assign vs Merge
share save run
Babel Compiler v6.4.4
Copyright (c) 2014-2015 Sebastian McKenzie
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 13/55
⭐ Use composição para montar estado
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 14/55
LIÇÃO 3
Make your state immutable
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 15/55
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 16/55
class ItemList extends Component {
constructor() {
this.state.items = Store.getState().items
}
// assume this method is called when our store was updated
onStoreUpdate() {
this.setState({items: Store.getState().items })
}
addItem(item) {
let items = this.state.items
items.push(item) // Bad 💩
}
render() {
return (
<ItemEditor onAdd = {this.addItem} />
/*...*/
)
}
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 17/55
class ItemList extends Component {
constructor() {
this.state.items = Store.getState().items
}
// assume this method is called when our store was updated
onStoreUpdate() {
this.setState({items: Store.getState().items })
}
addItem(item) {
let items = this.state.items
items.push(item) // State mutated in STORE!
}
render() {
return (
<ItemEditor onAdd = {this.addItem} />
/*...*/
)
}
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 18/55
SOLUÇÃO SUBÓTIMA 😕
addItem(item) {
let items = _.cloneDeep(this.state.items)
items.push(item) // store won't be mutated
Store.update({items: items})
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 19/55
SOLUÇÃO MELHOR 😊
constructor() {
// Copy by reference for immutable data is ok!
this.state.items = Store.getImmutableState().get('items')
}
// ...
addItem(item) {
// you cannot simply add an item to the list, you need to use the API
let copiedItems = Immutable(this.state.items).asMutable()
copiedItems.push(item)
// assumes that update() makes the state somehow immutable
Store.update({items: copiedItems})
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 20/55
COMO FAZER IMUTÁVEL? 🤔
New Repl ohagermy repls community
BETA
DevCamp2017: Immutable
share save run
Babel Compiler v6.4.4
Copyright (c) 2014-2015 Sebastian McKenzie
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 21/55
COMO FAZER IMUTÁVEL? 🤔
https://github.com/facebook/immutable-js [60KiB]
https://github.com/rtfeldman/seamless-immutable [8KiB]
https://github.com/Yomguithereal/baobab [33KiB]
https://github.com/planttheidea/crio [51KiB]
... etc etc pp
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 22/55
THE GOOD THINGS 🍺
// optimize our rendering process (React-wise)
shouldComponentUpdate(nextProps, nextState){
// comparing by reference
return this.state.items !== nextState.items;
}
⭐ Evite alterações acidentais (bom para times)
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 23/55
THE BAD THING(S) 🍋
⭐ Mais verboso/trabalhoso para alterar
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 24/55
LIÇÃO 4
Flatten the state
Keep it simple 2
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 25/55
const posts = [
{
"id": 123,
"author": {
"id": 1,
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [
{
"id": 324,
"commenter": {
"id": 2,
"name": "Nicole",
"text" : "Nicole + Paul = Love 💕"
}
},
{
"id": 325,
"commenter": {
"id": 5,
"name": "Klaus",
"text" : "Yo, Mann. Geiler Scheiss!"
}
}
]
}
];
PROBLEM👾
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 26/55
UPDATE
posts.find( p => p.id === 123).author.name = 'Dude';
UPDATE IMMUTABLE
// update
const post = posts.find( p => p.id === 123);
// seamless-immutable API
const updatedPost = Immutable.setIn(post, ["author", "name"], "Elmar");
// insert
const atIndex = posts.findIndex( p => p.id === 123);
const newPost = { /* ... */ };
posts.slice(0, atIndex).concat(newPost).concat(posts.slice(atIndex+1)); // 😲 WTF?
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 27/55
const normalizedPosts = {
"posts": [
{
"id": 123,
"authorId": 1,
"title": "My awesome blog post",
"comments": [324, 325]
}
// ... more posts
],
"comments": [
{
"id": 324,
"authorId": 2
}, {
"id": 325,
"authorId": 5
}
],
"authors": [
{
"id": 1,
"name": "Paul"
},
{
"id": 2,
"name": "Nicole"
}, {
FLATTENED/NORMALIZED
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 28/55
⭐ "Estados rasos" simpli cam acesso/alterações
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 29/55
LIÇÃO 5
Determine your state's scope
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 30/55
STORY TIME
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 31/55
ONCE UPON A TIME
⚫ Quis criar um
suggestion/autocomplete
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 32/55
SO SAD
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 33/55
ACTION CREATOR
// Action Creator - ES5 old school style, babe
function fetchSuggestions(componentId, url, searchTerm){
var suggestionService = new GenericService(url);
suggestionService.getAll({
textFilter: searchTerm,
//...
})
.then(function (suggestions) {
this.dispatch('fetchSuggestions', {
componentId : componentId, // Hu, I need to manage the component instance!
suggestions : suggestions
});
}.bind(this));
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 34/55
SUGGESTION STORE
var _suggestions = {};
var suggestionStore = {
// get the suggestions for specific component
getSuggestions : function(componentId){ // WTF?
return _suggestions[componentId]; // WTF?
},
// called on dispatch('fetchSuggestions',...)
// -- nanoflux uses a convention based auto-mapping
onFetchSuggestions : function(data){
_suggestions[data.componentId] = Immutable(data.suggestions); // WTF?
this.notifyListeners();
}
};
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 35/55
⭐ A LISTA DE SUGESTÕES NÃO É
ESTADO DA APLICAÇÃO
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 36/55
⭐ A LISTA DE SUGESTÕES É ESTADO
DO COMPONENTE!
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 37/55
COMO DETERMINAR O ESCOPO DO
ESTADO?
Componente Aplicação
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 38/55
LIÇÃO 6
Manage your state globally
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 39/55
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 40/55
BASIC PRINCIPLES
⭐ Deixar acessível por todos os componentes
⭐ Alterar o estado apenas em um único ponto bem de nido
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 41/55
ACESSO AO ESTADO
Reactive - Hollywood principle: Don't call us, we call you! 📞
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 42/55
OBSERVER/PUBSUB
function notify(listeners, state) {
for(const pn in listeners){
const l = listeners[pn]
l.f.call(l.c, state)
}
}
class ApplicationStateManager {
constructor(){
this._listenerCount = 0;
this._listeners = {};
this._state = {};
}
listen(fn, ctx) {
// use object map instead of array (is smaller and faster)
this._listeners[++this._listenerCount] = { f: fn, c: ctx }
return this._listenerCount
}
unlisten(listenerId) {
delete this._listeners[listenerId];
}
update(args){
//... update stuff
notify(this._listeners, this._state)
}
getState() { return this._state }
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 43/55
USING BROWSER EVENTS
class ApplicationStateManager {
constructor(){
this._state = {};
}
update(args){
//... update stuff
window.dispatchEvent(new CustomEvent('stateUpdate', { 'detail': this._state }) )
}
getState() { return this._state }
}
// Usage
const mgr = new ApplicationStateManager();
window.addEventListener('stateUpdate', e => { console.log('state updated', e.detail)} )
mgr.update( {} ) // fake update here!
window.removeEventListener('stateUpdate');
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 44/55
ALTERAR O ESTADO
"Single Source of Truth"🍺
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 45/55
function deepFreeze(obj) {
for(let pn in obj) {
if (typeof obj[pn] === 'object')
deepFreeze(obj[pn])
}
return Object.freeze(obj)
}
class ApplicationStateManager {
constructor(){
// ...
this._state = {};
}
/* ... */
update(fn){
let s = this._state;
s = deepFreeze(Object.assign({}, s, fn(s)))
notify(this._listeners, s)
}
getState() { return this._state } // immutable, YAY!
}
UPDATE
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 46/55
UPDATE USAGE
function addItem(newItem){
appStateManager.update( state => {
// need to copy the state, as it is immutable
let items = _.cloneDeep(state.items || []);
items.push(newItem);
return {items: items}; // return new state slice
})
}
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 47/55
BASIC PRINCIPLES RECAP
⭐ Acesso ao estado de forma reativa com Observer/PubSub ou similar
⭐ Estado alterável apenas pelo próprio State Manager (imutabilidade força)
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 48/55
LIÇÃO 7
Break huge states in parts
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 49/55
BEST PRACTICES OF THE TOP DOGS
https://facebook.github.io/ ux/docs/ ux-utils.html#store
http://redux.js.org/docs/recipes/reducers/UsingCombineReducers.htm
https://mobx.js.org/best/store.html
⭐ Flux suporta múltiplos "Stores"
⭐ Redux promove vários "Reducers"
⭐ MobX recomenda "Domain Stores"
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 50/55
SEPARAÇÃO POR CONTEXTO -
APLICAÇÃO
Noti cações globais, Modais, Indicadores de Carregamento, etc.
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 51/55
SEPARAÇÃO POR CONTEXTO -
DOMÍNIO
Pedidos, Serviços, Produtos, Compras, Vendas etc.
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 52/55
RESUMO
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 53/55
JUST FOR FUN!
Stappo Demo
This small demo is built with RiotJS, BlazeCSS and Webpack
Clear All Add
Your items Stappo Stats
npmnpm v0.0.7v0.0.7
Build Type Size [bytes]
Generic Bundle 1271
Web Bundle 1243
Generic 337
Web 274
Enter name of item to add...
No Items Here
What are you searching for?
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 54/55
274 BYTES!
function Stappo(a){function d(b){for(var a in
b)"object"==typeof b[a]&&d(b[a]);return
Object.freeze(b)}a=void 0===a?"stappo":a;var c=
{};this.update=function(b)
{c=d(Object.assign({},c,b()));window.dispatchEvent(new
CustomEvent(a,{detail:c}))};this.get=function(){return c}};
Fully reactive App State Manager with immutable states
https://github.com/ohager/stappo
6/29/2017 DevCamp 2017
https://ohager.github.io/devcamp2017_slides/#/?export& 55/55
DANKE!🤘
github.com/ohager
linkedin.com/in/oliverhager
devbutze.com

Más contenido relacionado

La actualidad más candente

Instances Behind the Scene: What happen when you click on «create a new insta...
Instances Behind the Scene: What happen when you click on «create a new insta...Instances Behind the Scene: What happen when you click on «create a new insta...
Instances Behind the Scene: What happen when you click on «create a new insta...
Scaleway
 

La actualidad más candente (20)

Introduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec JenkinsIntroduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec Jenkins
 
Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017
 
Introduction à l'intégration continue en PHP
Introduction à l'intégration continue en PHPIntroduction à l'intégration continue en PHP
Introduction à l'intégration continue en PHP
 
Git Merge, Resets and Branches
Git Merge, Resets and BranchesGit Merge, Resets and Branches
Git Merge, Resets and Branches
 
GitHub Pull Request Builder for Drupal
GitHub Pull Request Builder for DrupalGitHub Pull Request Builder for Drupal
GitHub Pull Request Builder for Drupal
 
Workshop presentation
Workshop presentationWorkshop presentation
Workshop presentation
 
Bootiful Development with Spring Boot and Angular - Spring I/O 2017
Bootiful Development with Spring Boot and Angular - Spring I/O 2017Bootiful Development with Spring Boot and Angular - Spring I/O 2017
Bootiful Development with Spring Boot and Angular - Spring I/O 2017
 
Bootiful Development with Spring Boot and Vue - RWX 2018
Bootiful Development with Spring Boot and Vue - RWX 2018Bootiful Development with Spring Boot and Vue - RWX 2018
Bootiful Development with Spring Boot and Vue - RWX 2018
 
Hot Reloading with React - Experiences
Hot Reloading with React - ExperiencesHot Reloading with React - Experiences
Hot Reloading with React - Experiences
 
Development with Git and Gerrit - Eclipse DemoCamp Stuttgart - 2010-11-23
Development with Git and Gerrit - Eclipse DemoCamp Stuttgart - 2010-11-23Development with Git and Gerrit - Eclipse DemoCamp Stuttgart - 2010-11-23
Development with Git and Gerrit - Eclipse DemoCamp Stuttgart - 2010-11-23
 
WSO2Con ASIA 2016: Automate and Orchestrate DevOps
WSO2Con ASIA 2016: Automate and Orchestrate DevOpsWSO2Con ASIA 2016: Automate and Orchestrate DevOps
WSO2Con ASIA 2016: Automate and Orchestrate DevOps
 
Microservices for the Masses with Spring Boot and JHipster - RWX 2018
Microservices for the Masses with Spring Boot and JHipster - RWX 2018Microservices for the Masses with Spring Boot and JHipster - RWX 2018
Microservices for the Masses with Spring Boot and JHipster - RWX 2018
 
Intro. to Git and Github
Intro. to Git and GithubIntro. to Git and Github
Intro. to Git and Github
 
What's New in JHipsterLand - Devoxx Poland 2017
What's New in JHipsterLand - Devoxx Poland 2017What's New in JHipsterLand - Devoxx Poland 2017
What's New in JHipsterLand - Devoxx Poland 2017
 
DevOps 及 TDD 開發流程哲學
DevOps 及 TDD 開發流程哲學DevOps 及 TDD 開發流程哲學
DevOps 及 TDD 開發流程哲學
 
Front End Development for Back End Developers - Devoxx UK 2017
 Front End Development for Back End Developers - Devoxx UK 2017 Front End Development for Back End Developers - Devoxx UK 2017
Front End Development for Back End Developers - Devoxx UK 2017
 
Instances Behind the Scene: What happen when you click on «create a new insta...
Instances Behind the Scene: What happen when you click on «create a new insta...Instances Behind the Scene: What happen when you click on «create a new insta...
Instances Behind the Scene: What happen when you click on «create a new insta...
 
It's Not Continuous Delivery If You Can't Deploy Right Now
It's Not Continuous Delivery If You Can't Deploy Right NowIt's Not Continuous Delivery If You Can't Deploy Right Now
It's Not Continuous Delivery If You Can't Deploy Right Now
 
[Ultracode Munich #4] Short introduction to the new Android build system incl...
[Ultracode Munich #4] Short introduction to the new Android build system incl...[Ultracode Munich #4] Short introduction to the new Android build system incl...
[Ultracode Munich #4] Short introduction to the new Android build system incl...
 
Entwicklung mit Android Studio und Gradle
Entwicklung mit Android Studio und GradleEntwicklung mit Android Studio und Gradle
Entwicklung mit Android Studio und Gradle
 

Similar a Effective Application State Management (@DevCamp2017)

Developing modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular jsDeveloping modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular js
Shekhar Gulati
 
Testing of javacript
Testing of javacriptTesting of javacript
Testing of javacript
Lei Kang
 
Turku loves-storybook-styleguidist-styled-components
Turku loves-storybook-styleguidist-styled-componentsTurku loves-storybook-styleguidist-styled-components
Turku loves-storybook-styleguidist-styled-components
James Stone
 
SharePoint Framework, Angular and Azure Functions
SharePoint Framework, Angular and Azure FunctionsSharePoint Framework, Angular and Azure Functions
SharePoint Framework, Angular and Azure Functions
Sébastien Levert
 

Similar a Effective Application State Management (@DevCamp2017) (20)

Front End Development for Back End Developers - vJUG24 2017
Front End Development for Back End Developers - vJUG24 2017Front End Development for Back End Developers - vJUG24 2017
Front End Development for Back End Developers - vJUG24 2017
 
Bootiful Development with Spring Boot and Vue - Devnexus 2019
Bootiful Development with Spring Boot and Vue - Devnexus 2019Bootiful Development with Spring Boot and Vue - Devnexus 2019
Bootiful Development with Spring Boot and Vue - Devnexus 2019
 
Automating Aegir Platform builds with Git; Fabric; and Drush
Automating Aegir Platform builds with Git; Fabric; and DrushAutomating Aegir Platform builds with Git; Fabric; and Drush
Automating Aegir Platform builds with Git; Fabric; and Drush
 
Developing modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular jsDeveloping modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular js
 
ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 VueJS cod...
ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 VueJS cod...ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 VueJS cod...
ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 VueJS cod...
 
Art & music vs Google App Engine
Art & music vs Google App EngineArt & music vs Google App Engine
Art & music vs Google App Engine
 
Testing of javacript
Testing of javacriptTesting of javacript
Testing of javacript
 
Firebase analytics event_201607
Firebase analytics event_201607Firebase analytics event_201607
Firebase analytics event_201607
 
Front End Development for Back End Developers - Denver Startup Week 2017
Front End Development for Back End Developers - Denver Startup Week 2017Front End Development for Back End Developers - Denver Startup Week 2017
Front End Development for Back End Developers - Denver Startup Week 2017
 
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
 
Front End Development for Backend Developers - GIDS 2019
Front End Development for Backend Developers - GIDS 2019Front End Development for Backend Developers - GIDS 2019
Front End Development for Backend Developers - GIDS 2019
 
Turku loves-storybook-styleguidist-styled-components
Turku loves-storybook-styleguidist-styled-componentsTurku loves-storybook-styleguidist-styled-components
Turku loves-storybook-styleguidist-styled-components
 
Building with Firebase
Building with FirebaseBuilding with Firebase
Building with Firebase
 
Real World Lessons in Progressive Web Application & Service Worker Caching
Real World Lessons in Progressive Web Application & Service Worker CachingReal World Lessons in Progressive Web Application & Service Worker Caching
Real World Lessons in Progressive Web Application & Service Worker Caching
 
SharePoint Framework, Angular and Azure Functions
SharePoint Framework, Angular and Azure FunctionsSharePoint Framework, Angular and Azure Functions
SharePoint Framework, Angular and Azure Functions
 
The Present and Future of the Web Platform
The Present and Future of the Web PlatformThe Present and Future of the Web Platform
The Present and Future of the Web Platform
 
[English][Test Girls] Zero to Hero: Start Test automation with Cypress
[English][Test Girls] Zero to Hero: Start Test automation with Cypress[English][Test Girls] Zero to Hero: Start Test automation with Cypress
[English][Test Girls] Zero to Hero: Start Test automation with Cypress
 
Voluminous_Weibo
Voluminous_WeiboVoluminous_Weibo
Voluminous_Weibo
 
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
 
React HOCs, Context and Observables
React HOCs, Context and ObservablesReact HOCs, Context and Observables
React HOCs, Context and Observables
 

Último

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 

Último (20)

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 

Effective Application State Management (@DevCamp2017)