Public properties are state; public methods are actions. wire:click="add" POSTs the last snapshot and the call to /livewire-1a7d881b/update. Livewire 2,157 rebuilds the object, runs add(), re-renders, and returns HTML plus a new snapshot, which livewire.js morphs into the page (also filling the input, empty in the server HTML). The same request from curl 3,008 :
jq -n --arg t "$TOKEN" --arg s "$SNAPSHOT" '{_token: $t, components: [{snapshot: $s,
updates: {}, calls: [{method: "add", params: [], metadata: {}}]}]}' > body.json
curl -s -b jar -H 'Content-Type: application/json' -H 'X-Livewire: 1' -d @body.json \
"$URI" > resp.json
jq -c '.components[0].snapshot | fromjson | .data' resp.json
jq -r '.components[0].effects.html' resp.json | grep -o 'Total[^<]*'{"qty":2,"price":24.5}
Total: $49.00The snapshot is signed with an HMAC-SHA256 checksum: changing "qty":1 to 99 got HTTP 500, Livewire encountered corrupt data when trying to hydrate a component. A client can still set any public property and call any public method, so validate and authorize (Authorization), and mark server-only values #[Locked].
wire:model is deferred by default: the value travels with the next action. .live sends while typing (debounced 150 ms by default), .blur and .change on those events, and .number and .boolean cast. Livewire::test('cart-qty')->call('add') with assertSet() and assertSee() tests a component without a browser.