Updating the UI from Server pushes
WebSocket events become state updates like any other input. Your component already knows how to re-render when state changes. The difference is that the state change comes from a server push instead of a user click. Everything downstream is the same.
type Action =
| { type: 'book_added'; data: Book }
| { type: 'book_removed'; data: { id: number } }
| { type: 'stock_changed'; data: { id: number; stock: number } };
function booksReducer(state: Book[], action: Action): Book[] {
switch (action.type) {
case 'book_added':
return [...state, action.data];
case 'book_removed':
return state.filter((b) => b.id !== action.data.id);
case 'stock_changed':
return state.map((b) =>
b.id === action.data.id ? { ...b, stock: action.data.stock } : b,
);
}
}A reducer keeps the event handling logic in one predictable place.
A reducer is the right tool for this job once you have more than one event type. All the event handling lives in one pure function. It is easy to test in isolation, easy to extend, and easy to reason about when the server starts sending new event types.
Quiz: Quiz
Loading practice…