or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

computed.mdeffect-scopes.mdeffects.mdindex.mdreactive-objects.mdrefs.mdutilities.mdwatchers.md

refs.mddocs/

0

# Reactive References

1

2

Reactive references provide fine-grained reactivity for primitive values and objects by wrapping them in a reactive container that tracks access and mutations.

3

4

## Capabilities

5

6

### ref()

7

8

Creates a reactive and mutable ref object with a single `.value` property that holds the wrapped value.

9

10

```typescript { .api }

11

/**

12

* Creates a reactive and mutable ref object

13

* @param value - The value to wrap in a ref

14

* @returns A reactive ref object with a `.value` property

15

*/

16

function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T>;

17

function ref<T = any>(): Ref<T | undefined>;

18

19

interface Ref<T = any, S = T> {

20

get value(): T;

21

set value(_: S);

22

[RefSymbol]: true;

23

}

24

```

25

26

**Usage Examples:**

27

28

```typescript

29

import { ref } from "@vue/reactivity";

30

31

// Basic ref usage

32

const count = ref(0);

33

console.log(count.value); // 0

34

count.value = 5;

35

console.log(count.value); // 5

36

37

// Object ref (will be deeply reactive)

38

const user = ref({ name: "Alice", age: 25 });

39

user.value.name = "Bob"; // Triggers reactivity

40

user.value = { name: "Charlie", age: 30 }; // Triggers reactivity

41

42

// Array ref

43

const items = ref([1, 2, 3]);

44

items.value.push(4); // Triggers reactivity

45

items.value = [5, 6, 7]; // Triggers reactivity

46

```

47

48

### shallowRef()

49

50

Creates a shallow reactive ref where only the `.value` access is reactive, not the object itself.

51

52

```typescript { .api }

53

/**

54

* Creates a shallow reactive ref - only .value access is reactive

55

* @param value - The value to wrap in a shallow ref

56

* @returns A shallow ref object

57

*/

58

function shallowRef<T>(value: T): ShallowRef<T>;

59

function shallowRef<T = any>(): ShallowRef<T | undefined>;

60

61

interface ShallowRef<T = any, S = T> extends Ref<T, S> {

62

[ShallowRefMarker]?: true;

63

}

64

```

65

66

**Usage Examples:**

67

68

```typescript

69

import { shallowRef, triggerRef } from "@vue/reactivity";

70

71

const obj = shallowRef({ count: 1 });

72

73

// This will NOT trigger effects because shallow refs only track .value access

74

obj.value.count = 2;

75

76

// To trigger effects after mutating, use triggerRef

77

triggerRef(obj);

78

79

// This WILL trigger effects (replacing .value)

80

obj.value = { count: 3 };

81

```

82

83

### isRef()

84

85

Checks if a value is a ref object.

86

87

```typescript { .api }

88

/**

89

* Checks if a value is a ref object

90

* @param r - Value to check

91

* @returns True if the value is a ref

92

*/

93

function isRef<T>(r: Ref<T> | unknown): r is Ref<T>;

94

function isRef(r: any): r is Ref;

95

```

96

97

**Usage Examples:**

98

99

```typescript

100

import { ref, isRef } from "@vue/reactivity";

101

102

const count = ref(0);

103

const plainValue = 42;

104

105

console.log(isRef(count)); // true

106

console.log(isRef(plainValue)); // false

107

console.log(isRef({ value: 42 })); // false (not a real ref)

108

```

109

110

### unref()

111

112

Returns the inner value if the argument is a ref, otherwise returns the argument itself.

113

114

```typescript { .api }

115

/**

116

* Returns the inner value if the argument is a ref, otherwise returns the argument

117

* @param ref - A ref or any value

118

* @returns The unwrapped value

119

*/

120

function unref<T>(ref: MaybeRef<T> | ComputedRef<T>): T;

121

```

122

123

**Usage Examples:**

124

125

```typescript

126

import { ref, unref } from "@vue/reactivity";

127

128

const count = ref(42);

129

const plainValue = 100;

130

131

console.log(unref(count)); // 42

132

console.log(unref(plainValue)); // 100

133

134

// Useful for functions that accept both refs and plain values

135

function useValue(maybeRef: MaybeRef<number>): number {

136

return unref(maybeRef) * 2;

137

}

138

139

console.log(useValue(count)); // 84

140

console.log(useValue(50)); // 100

141

```

142

143

### toValue()

144

145

Normalizes values/refs/getters to values. Similar to `unref` but also handles getter functions.

146

147

```typescript { .api }

148

/**

149

* Normalizes values/refs/getters to values

150

* @param source - A ref, getter function, or plain value

151

* @returns The resolved value

152

*/

153

function toValue<T>(source: MaybeRefOrGetter<T>): T;

154

```

155

156

**Usage Examples:**

157

158

```typescript

159

import { ref, toValue } from "@vue/reactivity";

160

161

const count = ref(42);

162

const getValue = () => 100;

163

const plainValue = 200;

164

165

console.log(toValue(count)); // 42

166

console.log(toValue(getValue)); // 100

167

console.log(toValue(plainValue)); // 200

168

```

169

170

### toRef()

171

172

Normalizes values/refs/getters into refs, or creates a ref for a property on a reactive object.

173

174

```typescript { .api }

175

/**

176

* Converts a value to a ref

177

* @param value - Value to convert to ref

178

* @returns A ref containing the value

179

*/

180

function toRef<T>(value: T): ToRef<T>;

181

182

/**

183

* Creates a ref for a property on a reactive object

184

* @param object - Reactive object

185

* @param key - Property key

186

* @returns A ref linked to the object property

187

*/

188

function toRef<T extends object, K extends keyof T>(object: T, key: K): ToRef<T[K]>;

189

190

/**

191

* Creates a ref for a property with a default value

192

* @param object - Reactive object

193

* @param key - Property key

194

* @param defaultValue - Default value if property is undefined

195

* @returns A ref linked to the object property with default

196

*/

197

function toRef<T extends object, K extends keyof T>(

198

object: T,

199

key: K,

200

defaultValue: T[K]

201

): ToRef<Exclude<T[K], undefined>>;

202

```

203

204

**Usage Examples:**

205

206

```typescript

207

import { reactive, toRef } from "@vue/reactivity";

208

209

const state = reactive({ count: 0, name: "Vue" });

210

211

// Create refs from reactive object properties

212

const countRef = toRef(state, "count");

213

const nameRef = toRef(state, "name");

214

215

console.log(countRef.value); // 0

216

countRef.value = 5; // Updates state.count

217

console.log(state.count); // 5

218

219

// Convert plain value to ref

220

const plainRef = toRef(42);

221

console.log(plainRef.value); // 42

222

```

223

224

### toRefs()

225

226

Converts a reactive object to a plain object where each property is a ref that maintains reactivity connection to the original object.

227

228

```typescript { .api }

229

/**

230

* Converts a reactive object to refs for each property

231

* @param object - Reactive object to convert

232

* @returns Object with ref properties

233

*/

234

function toRefs<T extends object>(object: T): ToRefs<T>;

235

```

236

237

**Usage Examples:**

238

239

```typescript

240

import { reactive, toRefs } from "@vue/reactivity";

241

242

const state = reactive({

243

count: 0,

244

name: "Vue",

245

items: [1, 2, 3]

246

});

247

248

// Convert to refs - useful for destructuring

249

const { count, name, items } = toRefs(state);

250

251

console.log(count.value); // 0

252

count.value = 10; // Updates state.count

253

console.log(state.count); // 10

254

255

// Commonly used in composition functions

256

function useCounter() {

257

const state = reactive({ count: 0 });

258

259

return {

260

...toRefs(state),

261

increment: () => state.count++

262

};

263

}

264

```

265

266

### customRef()

267

268

Creates a customized ref with explicit control over dependency tracking and updates.

269

270

```typescript { .api }

271

/**

272

* Creates a customized ref with explicit control over tracking and triggering

273

* @param factory - Factory function that receives track and trigger callbacks

274

* @returns A custom ref object

275

*/

276

function customRef<T>(factory: CustomRefFactory<T>): Ref<T>;

277

278

type CustomRefFactory<T> = (

279

track: () => void,

280

trigger: () => void

281

) => {

282

get: () => T;

283

set: (value: T) => void;

284

};

285

```

286

287

**Usage Examples:**

288

289

```typescript

290

import { customRef } from "@vue/reactivity";

291

292

// Debounced ref that delays updates

293

function useDebouncedRef<T>(value: T, delay = 200) {

294

let timeout: number;

295

296

return customRef<T>((track, trigger) => {

297

return {

298

get() {

299

track(); // Track dependency

300

return value;

301

},

302

set(newValue: T) {

303

clearTimeout(timeout);

304

timeout = setTimeout(() => {

305

value = newValue;

306

trigger(); // Trigger updates

307

}, delay);

308

}

309

};

310

});

311

}

312

313

const debouncedValue = useDebouncedRef("hello");

314

```

315

316

### triggerRef()

317

318

Force trigger effects that depend on a shallow ref. Used when you have made deep mutations to the inner value of a shallow ref.

319

320

```typescript { .api }

321

/**

322

* Force trigger effects that depend on a shallow ref

323

* @param ref - The shallow ref to trigger

324

*/

325

function triggerRef(ref: Ref): void;

326

```

327

328

**Usage Examples:**

329

330

```typescript

331

import { shallowRef, triggerRef, effect } from "@vue/reactivity";

332

333

const obj = shallowRef({ count: 1 });

334

335

effect(() => {

336

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

337

});

338

339

// This won't trigger the effect (shallow ref)

340

obj.value.count = 2;

341

342

// Manually trigger effects after mutation

343

triggerRef(obj); // Now the effect runs

344

```

345

346

### proxyRefs()

347

348

Returns a proxy that shallowly unwraps properties that are refs, allowing direct property access without `.value`.

349

350

```typescript { .api }

351

/**

352

* Creates a proxy that automatically unwraps ref properties

353

* @param objectWithRefs - Object containing ref properties

354

* @returns Proxy with automatic ref unwrapping

355

*/

356

function proxyRefs<T extends object>(objectWithRefs: T): ShallowUnwrapRef<T>;

357

```

358

359

**Usage Examples:**

360

361

```typescript

362

import { ref, proxyRefs } from "@vue/reactivity";

363

364

const refs = {

365

count: ref(0),

366

name: ref("Vue"),

367

plainValue: 42

368

};

369

370

const proxy = proxyRefs(refs);

371

372

// Access without .value

373

console.log(proxy.count); // 0 (unwrapped from ref)

374

console.log(proxy.name); // "Vue" (unwrapped from ref)

375

console.log(proxy.plainValue); // 42 (plain value)

376

377

// Assignment unwraps refs

378

proxy.count = 5; // Same as refs.count.value = 5

379

proxy.name = "React"; // Same as refs.name.value = "React"

380

```

381

382

## Types

383

384

```typescript { .api }

385

// Core ref types

386

type MaybeRef<T = any> = T | Ref<T> | ShallowRef<T> | WritableComputedRef<T>;

387

type MaybeRefOrGetter<T = any> = MaybeRef<T> | ComputedRef<T> | (() => T);

388

389

// Conversion types

390

type ToRef<T> = IfAny<T, Ref<T>, [T] extends [Ref] ? T : Ref<T>>;

391

type ToRefs<T = any> = {

392

[K in keyof T]: ToRef<T[K]>;

393

};

394

395

// Unwrapping types

396

type UnwrapRef<T> = T extends ShallowRef<infer V, unknown>

397

? V

398

: T extends Ref<infer V, unknown>

399

? UnwrapRefSimple<V>

400

: UnwrapRefSimple<T>;

401

402

type ShallowUnwrapRef<T> = {

403

[K in keyof T]: DistributeRef<T[K]>;

404

};

405

406

// Custom ref factory type

407

type CustomRefFactory<T> = (

408

track: () => void,

409

trigger: () => void

410

) => {

411

get: () => T;

412

set: (value: T) => void;

413

};

414

```