Let's build a Reactivity System


Conversational Intelligence Platform
Quality Management & More
Speech-to-Text for Mixed Languages & Multi-parties
Tone & Emotions
Intent & Entity Detection
Praveen Puglia
@praveenpuglia



Fun With Flags - praveenpuglia.com/fun-with-flags
Reactivity
🤬
😐
👊
😵
🎁
🤩
Not happening!
Totally Possible
*secretly wishes that Devfest organizers are listening to all this*
- 
What made the text change from "Follow" to "Following" ?
 - What changed the appearance of the button?
 
// Initialize
isFollowing = false;
followButtonText  = isFollowing ? 'Following' : 'Follow';
// At a later point in time
// CALL THE API TO FOLLOW
// Om phat swaha! ✋
isFollowing = true;
    FRAMEOWRKS
Build / Update UI from Data Model
Make UI react to Data Changes automatically
Without touching the actual DOM...sort of
🙀
let number = 10;
let square = number * number
console.log(square); // 100number = 20
console.log(square); // 100 NOT 400// Initialize
isFollowing = false;
followButtonText  = isFollowing ? 'Following' : 'Follow';
// At a later point in time
// CALL THE API TO FOLLOW
// Om phat swaha! ✋
isFollowing = true;
    🙋♂️We want a spreadsheet
Kyun.js

addEventListener()
    🥁
🥁
🥁
🥁
🥁
🥁
document.body.addEventListener('mousemove', 
({ x, y }) => {
  console.log({ x, y });
});> Object {x: 576, y: 281}
> Object {x: 577, y: 282}
> Object {x: 578, y: 283}
> Object {x: 579, y: 284}addEventListener()
    - 
    stores the handlers somewhere.
 - 
    something says that the event has triggered.
 - executes all handlers when the event triggers.
 
🥁
🥁
🥁
🥁
🥁
🥁
🤔
// Storage
const handlers = [];
let number = 10;
let square = 0
// Mystery
let currentHandler = null;
// The one that stores the handler
function addPropertyHandler() {
  handlers.push(currentHandler)
}
// The one that executes all handlers
function notifyHandlers() {
  handlers.forEach(handler => handler())
}
currentHandler = () => {
  square = number * number;
}
// store the handler
addPropertyHandler();
currentHandler();
console.log(square); // 100
number = 20;
notifyHandlers();
console.log(square); // 400number = 10;
notifyHandlers();
console.log(square); // 100
number = 20;
notifyHandlers();
console.log(square); // 400
number = 30;
notifyHandlers();
console.log(square); // 900number = 10;
square; // 100
number = 20
square; // 400
    🏁
addEventListener()
({x, y}) => {
  console.log({x, y})
}mousemove
() => {
  alert('Clicked!')
}click
Our Solution
() => {
  square = number * number;
}handlers
() => {
  msg = `Hello ${name}`;
}- 🎢 Scale the solution.
 - 📦 Store automatically.
 - 🔔 Notify automatically.
 
class Dep {
  constructor() {
    this.handlers = new Set();
  }
  depend() {
    // same as addPropertyListener
    if(currentHandler) {
      this.handlers.add(currentHandler);
    }
  }
  
  notify() {
    // same as notifyHandlers
    this.handlers.forEach(
      handler => handler()
    );
  }
}🎢
let currentHandler = null;
let dep = new Dep();
let number = 10;
let square = 0
currentHandler = () => {
  square = number * number;
}
dep.depend();
currentHandler();
console.log(square); // 100
number = 20;
dep.notify();
console.log(square); // 400🎢
🎢
() => {
  square = number * number;
}number
() => {
  message = `Hello ${name}`;
}name
depend() {
  // same as addPropertyListener
  if(currentHandler) {
    this.handlers.add(currentHandler);
  }
}JS can execute
only one function
at a time
let currentHandler = null;
currentHandler = () => {
  square = number * number
}
dep.depend();
currentHandler();
currentHandler = null;function watcher(handler) {
  currentHandler = handler;
  dep.depend();
  currentHandler();
  currentHandler = null;
}
watcher(() => {
  square = number * number;
});🎢
But where is the attach instance of Dep part?
🎢
We need a way to know when our data was touched
🎢
Object.defineProperty()
let data = {};
Object.defineProperty(data, 'a', {
  get() {
    console.log("data.a was accessed");
  },
  set() {
    console.log("data.a was modified");
  }
})Use data Object
// FROM
let number = 10;
// TO
let data = {number: 10}🎢
Make one reactive
let internalValue = data.number;
let dep = new Dep();
Object.defineProperty(data, 'number', {
  get() { // number is accessed.
    dep.depend();
    return internalValue;
  },
  set(newVal) { // number is updated.
    internalValue = newVal;
    dep.notify();
  }
})🎢
📦
🔔
number = 10;
square; // 100
number = 20
square; // 400
    🏁

set() {
  dep.notify();
}Make all reactive
Object.keys(data).forEach(key => {
  let internalValue = data[key];
  const dep = new Dep();
  Object.defineProperty(data, key, {
    get() { 
      dep.depend();
      return this.internalValue;
    }
    set(newVal) { 
      this.internalValue = newVal;
      dep.notify();
    }
  })
});🎢
📦
🔔
Converter
let currentHandler = null;
function watcher(handler) {
  currentHandler = handler;
  dep.depend();
  currentHandler();
  currentHandler = null;
}
watcher(() => {
  square = number * number;
});let currentHandler = null;
function watcher(handler) {
  currentHandler = handler;
  currentHandler();
  currentHandler = null;
}
watcher(() => {
  square = number * number;
});get() {
  dep.depend();
}
Before
After
- 🎢 Scale the solution. ✅
 - 📦 Store automatically. ✅
 - 🔔 Notify automatically. ✅
 
number = 10;
square; // 100
number = 20
square; // 400
    🏁

🎉
🎈
Kyun.js
But how does the render thingy?
template
</>
render
()
watcher
👁
A
Framework
Is
Born

🙍♂️Caveats
Must declare reactive properties beforehand
🙍♂️
new Vue({
  data() {
    return {
      number : 10
    }
  }
})Adding reactive property
🙍♂️
Vue.set(vm.someObject, 'b', 2)
// OR
this.$set(this.someObject, 'b', 2)Adding / removing items in arrays
🙍♂️
this.todos[this.todos.length] = "do nothing"; // 👎
this.todos.push("do nothing"); // 👍
this.todos = [...this.todos, "do nothing"];🦹♀️PROXIES FOR THE FUTURE
- 
No need to use $set() to add a new reactive property.
 - 
Setting arr[key] = 'wow' will also trigger change detection.
 - 
Double the speed. Half the memory.
 - With the exact same API that we all love.
 
🦹♀️
We now have better understanding of Vue internals & the problems associated with it.
😇
Praveen Puglia
@praveenpuglia




Copy of Understanding Vue's Reactivity System by Building One
By Praveen Puglia
Copy of Understanding Vue's Reactivity System by Building One
- 81