Add one interaction
The user types into a search input. The application must remember the search before it decides what to display.
There are three small steps:
- Listen to what the user does.
- Save the new value in state.
- Ask the interface to display the new state.
const searchInput = document.querySelector('#search');
searchInput.addEventListener('input', (event) => {
state.search = event.currentTarget.value;
render();
});
For this lesson, let render() show both the current search and all items. Filtering comes next.
function render() {
document.querySelector('#current-search').textContent = state.search;
renderResources(state.items);
}
Trace the action
User types "state"
|
v
input event
|
v
state.search = "state"
|
v
render()
|
v
interface reflects "state"
The order matters. If render() runs first, it reads the old search value and produces the old interface.
Why not update only the DOM?
This handler appears to work:
searchInput.addEventListener('input', (event) => {
document.querySelector('#current-search').textContent = event.currentTarget.value;
});
But the application has forgotten the search. Another render would read the old state.search and overwrite the visible value. Two places now disagree about what is current.
The DOM is the screen, not the application's notebook. Write the new fact in the notebook first, then refresh the screen from that notebook.
Predict the order
searchInput.addEventListener('input', (event) => {
render();
state.search = event.currentTarget.value;
});
If the user types web, what value does render() read? It reads the previous value. Fix the order, then describe the difference in one sentence.
Use this spoken test: "The user typed web. The application saved web. The application displayed the result for web." If the code does not follow that order, the flow is wrong.
What to remember
A user event expresses an intention. Record that intention in state first, derive the required result, then render. This repeatable loop is a foundation that frameworks later help manage.