---
tags: brew-js
---
# Observing changes
By default the `App` instance is observable.
See also [watchable](/@misonou/zeta-dom#watchable).
## `app.watch`
```typescript
brew<{ myProp: number }>((app) => {
app.define({ myProp: 1 });
app.watch('myProp', (value, oldValue) => {
console.log(`New value is ${value}, old value is ${oldValue}`);
});
// generate log "New value is 2, old value is 1" to console
// asynchronously
app.myProp++;
});
```
Note that in general the listener is fired asynchronously, that means any consecutive update in a single event loop is merged:
```typescript
brew<{ myProp: number }>((app) => {
app.define({ myProp: 1 });
app.watch('myProp', (value, oldValue) => {
console.log(`New value is ${value}, old value is ${oldValue}`);
});
// generate exactly one log with message
// "New value is 3, old value is 1"
app.myProp++;
app.myProp++;
});
```
### `app.watchOnce`
```typescript
brew<{ myProp: number }>((app) => {
const promise = app.watchOnce('myProp', (value) => {
console.log(`myProp set to ${value}`);
});
// promise is resolved by this operation and thus
// generate log "myProp set to 1"
app.myProp = 1;
// promise is already resolved, thus
// generate no logs
app.myProp = 2;
});
```