Reactive Logging

console.log doesn’t understand reactivity. It logs once and forgets. When you’re debugging why something re-rendered, you need something better.

$inspect is console.log for reactive state. It re-runs whenever the value changes, showing you exactly when updates happen.

Basic Usage

<script>
  let count = $state(0);
  
  $inspect(count);
</script>

<button onclick={() => count++}>Increment</button>

Every time count changes, you’ll see it in the console:

init 0
update 1
update 2
update 3

The init happens when the component mounts. Each update is a change.

Inspecting Objects

For objects and arrays, $inspect shows the full value:

<script>
  let user = $state({ name: 'Alice', score: 0 });
  
  $inspect(user);
</script>

<button onclick={() => user.score++}>Add Point</button>
init { name: 'Alice', score: 0 }
update { name: 'Alice', score: 1 }
update { name: 'Alice', score: 2 }

Multiple Values

Inspect several values at once:

<script>
  let firstName = $state('Ada');
  let lastName = $state('Lovelace');
  
  $inspect(firstName, lastName);
</script>
init Ada Lovelace
update Augusta Lovelace

Custom Handling with .with()

The default logs to console. Use .with() for custom behavior:

<script>
  let data = $state({ x: 0, y: 0 });
  
  $inspect(data).with((type, value) => {
    if (type === 'update') {
      console.log('Data changed:', JSON.stringify(value));
    }
  });
</script>

The callback receives:

  • type: Either 'init' or 'update'
  • value: The current value (or values, if you passed multiple)

Breakpoint on Change

Drop into the debugger when a value changes:

<script>
  let count = $state(0);
  
  $inspect(count).with((type, value) => {
    if (type === 'update' && value > 10) {
      debugger; // Pause here when count exceeds 10
    }
  });
</script>

Trace to a File or Service

<script>
  let formData = $state({ email: '', password: '' });
  
  $inspect(formData).with((type, value) => {
    // Don't log passwords in production!
    if (import.meta.env.DEV) {
      console.table(value);
    }
  });
</script>

Debugging Derived Values

$inspect works with $derived too:

<script>
  let items = $state([1, 2, 3]);
  let total = $derived(items.reduce((a, b) => a + b, 0));
  
  $inspect(total);
</script>

Now you see when the derived value recalculates—useful for checking if expensive computations run more often than expected.

Remember to Remove

$inspect is for development. Remove it before production:

<script>
  let count = $state(0);
  
  // TODO: Remove before commit
  $inspect(count);
</script>

Or guard it:

<script>
  let count = $state(0);
  
  if (import.meta.env.DEV) {
    $inspect(count);
  }
</script>

When to Use $inspect

  • Unexpected re-renders: Is something updating more than it should?
  • State not updating: Is the change actually happening?
  • Timing issues: When exactly does this value change?
  • Derived confusion: Is the derived value recalculating correctly?

For deeper reactive tracing, check $inspect.trace() in the Svelte docs. But for most debugging, basic $inspect is all you need.