Skip to content

Instantly share code, notes, and snippets.

@themarcba
Last active February 5, 2024 11:52
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save themarcba/618264a12f277f10570c30759c592546 to your computer and use it in GitHub Desktop.
Save themarcba/618264a12f277f10570c30759c592546 to your computer and use it in GitHub Desktop.
Vue.js-like reactive state
<script>
let activeEffect
class Dep {
subscribers = new Set()
depend() {
if (activeEffect) this.subscribers.add(activeEffect)
}
notify() {
this.subscribers.forEach((sub) => sub())
}
}
function watchEffect(fn) {
const wrappedFn = () => {
activeEffect = wrappedFn
// clean up the deps
fn()
activeEffect = null
}
wrappedFn()
}
function reactive(obj) {
Object.keys(obj).forEach((key) => {
const dep = new Dep()
let value = obj[key]
Object.defineProperty(obj, key, {
get() {
dep.depend()
return value
},
set(newValue) {
if (newValue !== value) {
value = newValue
dep.notify()
}
},
})
})
return obj
}
// -------------------------
const state = reactive({
count: 1,
name: 'Marc',
})
watchEffect(() => {
console.log('👻 state changed', state.count, state.name)
})
setTimeout(() => {
state.count++
state.name = 'Johnny'
}, 1000)
setTimeout(() => {
state.count++
}, 2000)
setTimeout(() => {
state.count++
}, 3000)
</script>
@fender0ne
Copy link

Why do you need "wrappedFn " inside watchEffect? isn't it enough with the following function?

function watchEffect(fn) {
activeEffect = fn
fn()
activeEffect = null
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment