Data and components practice
Vale Media is combining request handling with reusable interface components. Some screens receive a delayed response or an empty list; others derive their content from props and local state. The data is fresh, and the same rules still apply. Await the response body, distinguish failed status from success, preserve zero, and let repeated actions update the current count. Each task is independent. Start by deciding which values are supplied inputs and which values the component must remember. That choice determines whether you need props, state, a derived expression, or a handler that reads the latest field.
<button>Load shipments</button><output></output><ul></ul>
body{font:16px/1.5 system-ui,sans-serif;color:#17243b;background:#fff;margin:20px}button,input,select{font:inherit}button,a,input,select{outline-offset:4px}button{cursor:pointer}main{max-width:100%}[hidden]{display:none!important}.cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.card{border:1px solid #94a3b8;padding:12px;min-width:0;overflow-wrap:anywhere}label{display:block}input,select{box-sizing:border-box;max-width:100%}ul{padding-left:24px}@media(max-width:600px){.cards{grid-template-columns:1fr}}
document.querySelector('button').onclick=async()=>{const response=await fetch('/shipments');if(!response.ok)throw new Error('Unexpected request failure');const items=await response.json();document.querySelector('ul').replaceChildren(...items.map(item=>{const li=document.createElement('li');li.textContent=item.name;return li;}));document.querySelector('output').textContent='Loaded: '+items.length;};
Read the markup and styles together, then trace the resulting control or layout.