State, render, commit

상태·렌더·커밋

A state update schedules a new UI calculation; the visible screen changes when that result is committed.

···
html
<div class="demo"><div class="head"><strong>STATE → UI</strong><span id="phase">update</span></div><div class="scene"><div class="chip box" id="state">state<br><b>0</b></div><span class="arrow">→</span><div class="chip box" id="render">render<br><b>0</b></div><span class="arrow">→</span><div class="chip box" id="commit">DOM<br><b>0</b></div></div><div class="foot"><span>update → render → commit</span><span>tap to step</span></div></div>
css
.demo{width:min(92vw,660px);height:min(86vh,310px);border:1px solid var(--line);border-radius:14px;background:var(--surface);padding:clamp(10px,2.5vmin,20px);display:flex;flex-direction:column;gap:clamp(6px,1.7vmin,12px);box-shadow:0 10px 35px rgba(0,0,0,.07);font:500 clamp(10px,2.8vmin,15px)/1.35 ui-monospace,SFMono-Regular,Consolas,monospace}
.head,.foot{display:flex;align-items:center;justify-content:space-between;gap:8px}.head strong{color:var(--accent);font-size:1.05em}.foot{color:var(--muted);font-size:.85em;min-height:1.4em}.scene{flex:1;min-height:0;position:relative;display:flex;align-items:center;justify-content:center;gap:clamp(5px,1.5vmin,12px)}.chip{border:1px solid var(--line);background:var(--bg);border-radius:7px;padding:.4em .6em;text-align:center}.on{border-color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 12%,var(--surface))!important;color:var(--accent)!important}.dim{opacity:.42}.arrow{color:var(--muted)}
.box{width:25%;height:60%;display:flex;flex-direction:column;justify-content:center}.box b{font-size:clamp(17px,6vmin,34px)}
js
let count=0,rendered=0,committed=0,step=0;const ids=["state","render","commit"];function advance(){if(step===0)count++;if(step===1)rendered=count;if(step===2)committed=rendered;[count,rendered,committed].forEach((v,i)=>{const box=document.getElementById(ids[i]);box.querySelector("b").textContent=v;box.classList.toggle("on",i===step)});document.getElementById("phase").textContent=["update","render","commit"][step];step=(step+1)%3}advance();const timer=setInterval(advance,800);document.querySelector(".demo").addEventListener("pointerdown",()=>{clearInterval(timer);advance()})

In React, a state update schedules rendering. The render phase calculates the next UI; the commit phase applies the needed DOM changes.

The demo separates counter state, calculated result, and visible value. They briefly differ between stages, then agree after commit. Avoid changing managed DOM directly so it diverges from state.

When to use

Use this model to understand when updates appear and to separate rendering from effects.

Open as page ↗