Refresh notification settings in the background
React · React · advanced · modification
Adds background refresh to the notification settings page: the one-shot load moves into a reusable refreshSettings() and an interval re-fetches every 20 seconds, so changes made on another device show up without a reload. Toggling still saves immediately and renders the server's response. Tested by flipping channels in one tab and watching a second tab pick the change up on the next tick.
The account settings area of a team app. Users commonly have the page open on two devices, which is why the poll exists. The API sits behind variable mobile latency; the PATCH response body is the full updated settings record.
Requirements
- The notification settings page shows the account's four channels as toggles, loaded from `GET /api/notification-settings` on mount.
- This PR adds a background refresh: while the page is mounted, settings are re-fetched every 20 seconds so changes made on another device appear without a reload. The interval is torn down on unmount. A failed background refresh is ignored silently (the next tick retries); a failed save shows the error message.
- Toggling a channel PATCHes the change; the server responds with the full updated settings record, which the UI must show. Toggles are disabled while a save is in flight.
- Overlapping responses must be applied newest-issued-wins: state produced by a later-issued request must never be overwritten by the response of an earlier-issued request. In particular, a background refresh that was already in flight when the user saved must not clobber the saved result when it lands. (Latency is variable; a GET routinely takes longer end-to-end than a subsequent PATCH.)
Files touched
- src/components/NotificationSettings.jsx
--- src/components/NotificationSettings.jsx
import { useEffect, useState } from 'react';
+
+const POLL_INTERVAL_MS = 20000;
const CHANNELS = [
/**
* Notification settings for the account page. The server owns the settings
- * record; the PATCH response is the full updated record.
+ * record; other devices can change it, so the page refreshes it in the
+ * background while mounted. The PATCH response is the full updated record.
*/
export function NotificationSettings() {
const [error, setError] = useState(null);
+ async function refreshSettings() {
+ try {
+ const res = await fetch('/api/notification-settings');
+ if (!res.ok) {
+ return; // transient — the next tick retries
+ }
+ const data = await res.json();
+ setSettings(data);
+ } catch {
+ // transient network failure — the next tick retries
+ }
+ }
+
useEffect(() => {
- async function load() {