ref
The ref
utility allows you to embed non-proxied objects within your Valtio state. This is useful for rare cases where you need to store complex objects, external library instances, or objects with accessors that should not be tracked by Valtio.
Objects wrapped in ref()
are treated as opaque and are not recursively proxied. Changes to their internal properties will not trigger updates.
Usage
Wrap the object you want to exclude from tracking with ref()
.
import { proxy, ref } from 'valtio';
const state = proxy({
count: 0,
// The document.body object will not be proxied.
domNode: ref(document.body),
// An array that will not be tracked.
untrackedUploads: ref([]),
});
Rules for Mutating ref
Objects
Once an object is wrapped in ref
, you should follow these rules:
-
Mutate the object directly: You can change the internal properties of the ref-wrapped object.
// ✅ DO: Mutate the object's contents directly. state.untrackedUploads.push({ id: 1, name: 'file.txt' });
-
Do not reassign the property: Reassigning the property on the parent proxy with a new
ref()
will trigger an update, but reassigning it with a new plain object will break theref
contract.// ✅ DO: This correctly triggers a re-render because the ref itself is replaced. state.untrackedUploads = ref(['new-file.txt']); // ❌ DON'T: This replaces the ref with a plain array, which will then be proxied. state.untrackedUploads = ['new-file.txt'];
When to Use ref
- External library instances: Storing instances like a Chart.js object or a D3 selection.
- DOM elements: While generally not recommended to store in state,
ref
is the correct way if you must. - Performance-critical large objects: If you have a very large, deeply nested object that doesn't need to be reactive, wrapping it in
ref
can prevent the overhead of proxying it.
CodeSandbox Demo
This example demonstrates using ref
to manage a list of file uploads without proxying the file objects themselves.
https://codesandbox.io/s/valtio-file-load-demo-oo2yzn