or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asset-resolution.mdbuiltin-components.mdcomponents.mdcomposition-helpers.mddependency-injection.mderror-handling.mdhydration.mdindex.mdinternal-render-helpers.mdlifecycle.mdreactivity.mdscheduler-timing.mdssr-context.mdvdom-rendering.mdwatch-effects.md

watch-effects.mddocs/

0

# Watch & Effects

1

2

Vue's watch system enables reactive observation of data changes with flexible scheduling and deep/shallow watching options. Effects provide low-level reactive behavior for custom reactivity patterns.

3

4

## Capabilities

5

6

### Watch Functions

7

8

Watch reactive data sources and execute callbacks when they change.

9

10

```typescript { .api }

11

/**

12

* Watches a single reactive source

13

* @param source - Reactive source to watch

14

* @param callback - Callback executed when source changes

15

* @param options - Watch configuration options

16

* @returns Function to stop the watcher

17

*/

18

function watch<T, Immediate extends Readonly<boolean> = false>(

19

source: WatchSource<T>,

20

callback: WatchCallback<T, Immediate extends true ? T | undefined : T>,

21

options?: WatchOptions<T, Immediate>

22

): WatchHandle;

23

24

/**

25

* Watches multiple reactive sources

26

* @param sources - Array of reactive sources to watch

27

* @param callback - Callback executed when any source changes

28

* @param options - Watch configuration options

29

* @returns Function to stop the watcher

30

*/

31

function watch<T extends MultiWatchSources, Immediate extends Readonly<boolean> = false>(

32

sources: [...T],

33

callback: WatchCallback<MapSources<T>, Immediate extends true ? Partial<MapSources<T>> : MapSources<T>>,

34

options?: WatchOptions<T, Immediate>

35

): WatchHandle;

36

37

/**

38

* Watches an object and its properties

39

* @param source - Object to watch

40

* @param callback - Callback executed when object changes

41

* @param options - Watch configuration options

42

* @returns Function to stop the watcher

43

*/

44

function watch<T extends object, Immediate extends Readonly<boolean> = false>(

45

source: T,

46

callback: WatchCallback<T, Immediate extends true ? T | undefined : T>,

47

options?: WatchOptions<T, Immediate>

48

): WatchHandle;

49

```

50

51

**Usage Examples:**

52

53

```typescript

54

import { ref, reactive, watch } from "@vue/runtime-core";

55

56

const count = ref(0);

57

const state = reactive({ name: "Vue", version: 3 });

58

59

// Watch a ref

60

const stopWatchingCount = watch(count, (newValue, oldValue) => {

61

console.log(`Count changed from ${oldValue} to ${newValue}`);

62

});

63

64

// Watch multiple sources

65

const stopWatchingMultiple = watch(

66

[count, () => state.name],

67

([newCount, newName], [oldCount, oldName]) => {

68

console.log(`Count: ${oldCount} -> ${newCount}`);

69

console.log(`Name: ${oldName} -> ${newName}`);

70

}

71

);

72

73

// Watch with immediate execution

74

watch(

75

() => state.version,

76

(version) => {

77

console.log(`Version: ${version}`);

78

},

79

{ immediate: true } // Runs immediately with current value

80

);

81

82

// Deep watch for objects

83

watch(

84

state,

85

(newState, oldState) => {

86

console.log("State changed:", newState);

87

},

88

{ deep: true } // Watches nested properties

89

);

90

91

// Cleanup

92

stopWatchingCount();

93

stopWatchingMultiple();

94

```

95

96

### WatchEffect Functions

97

98

Automatically track dependencies and re-run when they change.

99

100

```typescript { .api }

101

/**

102

* Runs a function immediately and re-runs when dependencies change

103

* @param effect - Function to run and track dependencies

104

* @param options - Effect configuration options

105

* @returns Function to stop the effect

106

*/

107

function watchEffect(

108

effect: WatchEffect,

109

options?: WatchEffectOptions

110

): WatchStopHandle;

111

112

/**

113

* Like watchEffect but runs after component updates (post-flush)

114

* @param effect - Function to run and track dependencies

115

* @param options - Effect configuration options

116

* @returns Function to stop the effect

117

*/

118

function watchPostEffect(

119

effect: WatchEffect,

120

options?: WatchEffectOptions

121

): WatchStopHandle;

122

123

/**

124

* Like watchEffect but runs synchronously

125

* @param effect - Function to run and track dependencies

126

* @param options - Effect configuration options

127

* @returns Function to stop the effect

128

*/

129

function watchSyncEffect(

130

effect: WatchEffect,

131

options?: WatchEffectOptions

132

): WatchStopHandle;

133

```

134

135

**Usage Examples:**

136

137

```typescript

138

import { ref, watchEffect, watchPostEffect, watchSyncEffect } from "@vue/runtime-core";

139

140

const count = ref(0);

141

const name = ref("Vue");

142

143

// Basic watchEffect

144

const stopEffect = watchEffect(() => {

145

console.log(`Count is ${count.value} and name is ${name.value}`);

146

});

147

// Runs immediately and when count or name changes

148

149

// watchEffect with cleanup

150

watchEffect((onInvalidate) => {

151

const timer = setInterval(() => {

152

console.log(`Timer: ${count.value}`);

153

}, 1000);

154

155

// Cleanup when effect is invalidated

156

onInvalidate(() => {

157

clearInterval(timer);

158

});

159

});

160

161

// Post-flush effect (runs after DOM updates)

162

watchPostEffect(() => {

163

// This runs after component DOM updates

164

console.log("DOM updated, count is:", count.value);

165

});

166

167

// Sync effect (runs synchronously)

168

watchSyncEffect(() => {

169

console.log("Sync effect, count:", count.value);

170

});

171

172

// Stop effects

173

stopEffect();

174

```

175

176

### Watch Options & Configuration

177

178

Configure watch behavior with various options.

179

180

```typescript { .api }

181

interface WatchOptions<T = any, Immediate extends boolean = boolean> {

182

/**

183

* Run the callback immediately with current value

184

*/

185

immediate?: Immediate;

186

187

/**

188

* Watch nested properties in objects and arrays

189

*/

190

deep?: boolean;

191

192

/**

193

* Flush timing: 'pre' (before updates), 'post' (after updates), 'sync' (synchronous)

194

*/

195

flush?: 'pre' | 'post' | 'sync';

196

197

/**

198

* Debug hook called when watcher triggers

199

*/

200

onTrack?: (event: DebuggerEvent) => void;

201

202

/**

203

* Debug hook called when watcher triggers

204

*/

205

onTrigger?: (event: DebuggerEvent) => void;

206

207

/**

208

* Indicates whether the job is allowed to recursively trigger itself

209

*/

210

allowRecurse?: boolean;

211

}

212

213

interface WatchEffectOptions {

214

/**

215

* Flush timing for the effect

216

*/

217

flush?: 'pre' | 'post' | 'sync';

218

219

/**

220

* Debug hook called when effect is tracked

221

*/

222

onTrack?: (event: DebuggerEvent) => void;

223

224

/**

225

* Debug hook called when effect is triggered

226

*/

227

onTrigger?: (event: DebuggerEvent) => void;

228

229

/**

230

* Indicates whether the job is allowed to recursively trigger itself

231

*/

232

allowRecurse?: boolean;

233

}

234

```

235

236

**Usage Examples:**

237

238

```typescript

239

import { ref, reactive, watch, watchEffect } from "@vue/runtime-core";

240

241

const user = reactive({

242

profile: {

243

name: "Alice",

244

settings: {

245

theme: "dark"

246

}

247

}

248

});

249

250

// Deep watching

251

watch(

252

user,

253

(newUser, oldUser) => {

254

console.log("User changed:", newUser);

255

},

256

{

257

deep: true, // Watch nested properties

258

immediate: true, // Run immediately

259

flush: 'post' // Run after DOM updates

260

}

261

);

262

263

// Flush timing examples

264

const count = ref(0);

265

266

// Pre-flush (default) - runs before DOM updates

267

watch(count, () => console.log("Pre-flush"), { flush: 'pre' });

268

269

// Post-flush - runs after DOM updates

270

watch(count, () => console.log("Post-flush"), { flush: 'post' });

271

272

// Sync - runs synchronously

273

watch(count, () => console.log("Sync"), { flush: 'sync' });

274

275

// Debug hooks

276

watchEffect(

277

() => {

278

console.log("Count:", count.value);

279

},

280

{

281

onTrack(e) {

282

console.log("Tracked:", e);

283

},

284

onTrigger(e) {

285

console.log("Triggered:", e);

286

}

287

}

288

);

289

```

290

291

## Types

292

293

```typescript { .api }

294

type WatchSource<T = any> = Ref<T> | ComputedRef<T> | (() => T);

295

296

type MultiWatchSources = (WatchSource<unknown> | object)[];

297

298

type MapSources<T> = {

299

[K in keyof T]: T[K] extends WatchSource<infer V>

300

? V

301

: T[K] extends object

302

? T[K]

303

: never;

304

};

305

306

type WatchCallback<V = any, OV = any> = (

307

value: V,

308

oldValue: OV,

309

onCleanup: OnCleanup

310

) => any;

311

312

type WatchStopHandle = () => void;

313

314

type WatchHandle = WatchStopHandle;

315

316

interface WatchEffect {

317

(onCleanup: OnCleanup): void;

318

}

319

320

type OnCleanup = (cleanupFn: () => void) => void;

321

322

interface DebuggerEvent {

323

effect: ReactiveEffect;

324

target: object;

325

type: TrackOpTypes | TriggerOpTypes;

326

key: any;

327

newValue?: any;

328

oldValue?: any;

329

oldTarget?: Map<any, any> | Set<any>;

330

}

331

332

enum TrackOpTypes {

333

GET = 'get',

334

HAS = 'has',

335

ITERATE = 'iterate'

336

}

337

338

enum TriggerOpTypes {

339

SET = 'set',

340

ADD = 'add',

341

DELETE = 'delete',

342

CLEAR = 'clear'

343

}

344

```