Selective hydration

선택적 하이드레이션

Hydration prioritizes a server-rendered region when the user interacts with it first.

···
html
<section class="stage"><div class="heading">SELECTIVE HYDRATION <span class="hint">interaction first</span></div><div class="hydration-lanes"><div class="lane" data-lane="feed"><b>FEED</b><span class="meter"><i></i></span><em>waiting</em></div><div class="lane" data-lane="comments"><b>COMMENTS</b><span class="meter"><i></i></span><em>waiting</em></div><div class="lane" data-lane="search"><b>SEARCH</b><span class="meter"><i></i></span><em>waiting</em></div></div><div class="caption" id="hydrate-note">Tap comments: its boundary takes priority</div></section>
css
.stage{width:min(94vw,780px);height:min(88vh,322px);padding:clamp(12px,3vmin,20px);border:1px solid var(--line);border-radius:16px;background:var(--surface);box-shadow:0 12px 36px #0001;display:flex;flex-direction:column;gap:clamp(7px,2vmin,14px);font:500 clamp(12px,3.5vmin,17px)/1.3 var(--font-sans,system-ui,sans-serif);overflow:hidden}.heading{display:flex;justify-content:space-between;align-items:center;gap:8px;font-weight:750;color:var(--accent)}.hint{color:var(--muted);font-size:clamp(12px,3.2vmin,14px);font-weight:500}.caption{margin-top:auto;color:var(--muted);font-size:clamp(12px,3.2vmin,14px)}.row{display:flex;gap:clamp(5px,1.5vmin,12px);align-items:center}.tile{padding:clamp(6px,1.8vmin,13px);border:1px solid var(--line);border-radius:9px;background:var(--bg);text-align:center;min-width:0}.arrow{color:var(--accent);font-weight:800}.stage [data-on]{transition:background .3s,border-color .3s,opacity .3s,transform .3s}.stage .on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,var(--surface));color:var(--accent)}.hydration-lanes{flex:1;display:flex;flex-direction:column;justify-content:center;gap:clamp(5px,1.8vmin,12px)}.lane{display:grid;grid-template-columns:34% 1fr 24%;align-items:center;gap:8px;padding:5px 8px;border:1px solid var(--line);border-radius:7px;background:var(--bg);font-size:clamp(12px,3vmin,15px)}.lane b{font-size:inherit}.lane em{font-style:normal;color:var(--muted);text-align:right}.meter{height:8px;border-radius:8px;background:var(--line);overflow:hidden}.meter i{display:block;width:0;height:100%;background:var(--accent);transition:width .35s}.lane.active{border-color:var(--accent)}.lane.active .meter i{width:100%}.lane.active em{color:var(--accent)}.stage small,.stage button,.stage .cards b,.stage .phase b,.stage .pair b,.stage .tree-mini b{font-size:clamp(12px,3.2vmin,14px)!important}
js
const lanes=[...document.querySelectorAll(".lane")],note=document.getElementById("hydrate-note");let step=0;function tick(){const active=step===0?[]:step===1?[1]:[1,0,2];lanes.forEach((lane,i)=>{lane.classList.toggle("active",active.includes(i));lane.querySelector("em").textContent=active.includes(i)?"ready":"waiting"});note.textContent=step===0?"Tap comments: its boundary takes priority":step===1?"Comments respond before other regions":"Remaining regions hydrate afterwards";step=(step+1)%3}tick();const timer=setInterval(tick,1050);lanes.forEach((lane,i)=>lane.addEventListener("pointerdown",()=>{clearInterval(timer);step=i===1?1:2;tick()}))

Selective hydration splits activation of server HTML across Suspense boundaries. React hydrates a boundary when its code is ready and can prioritize an unhydrated region that the user interacts with.

Priority can only help once the needed code is available; it cannot execute code that has not loaded. The demo prioritizes comments after an attempted interaction.

When to use

Use it when a server-rendered page has several interactive regions whose JavaScript becomes ready at different times.

Open as page ↗