Module Recap
Module 11 finished the social layer of Bulletin. Users can comment on posts, browse each other’s profiles, upvote from both the feed and detail page, search and sort the feed, and see meaningful error messages instead of broken UI.
What you learned
Section titled “What you learned”Callback props wire child-to-parent communication. CommentForm calls onCommentAdded(comment) which triggers handleCommentAdded in PostDetail — the parent controls the list, the child handles the form. React data flows down; callbacks flow up.
Custom hooks extract shared stateful logic. useUpvote holds the three-step optimistic pattern once. PostFeed and PostDetail both use it without duplicating a single line. Name custom hooks with use; call them at the top level of a component.
useMemo caches derived values. filteredPosts recomputes only when posts or search changes. Useful for any value computed from props/state that’s expensive or that you want to make semantically explicit.
Graceful failure has three layers.
- 404 catch-all route for bad URLs
- Per-request error messages with
axios.isAxiosErrorfor API failures ErrorBoundaryfor unexpected React runtime errors
Empty states are UX, not error handling. A list with no items needs a message that explains the absence and invites action — never silence or an error-red message.
The complete frontend component map
Section titled “The complete frontend component map”App (Router)├── Nav│ ├── Link: / (Home)│ ├── Link: /create (New Post) — shown when isAuthenticated│ └── Link: /login or Logout button├── Home (/)│ └── PostFeed│ ├── search input│ ├── sort select│ └── PostItem × N│ └── useUpvote├── PostDetail (/posts/:id)│ ├── useUpvote│ ├── Delete button (own posts only)│ └── Comments section│ ├── CommentList│ └── CommentForm (authenticated only)├── CreatePost (/create) — ProtectedRoute├── UserProfile (/users/:id)├── Login (/login)├── Register (/register)├── NotFound (* — catch-all)└── ErrorBoundary (wraps everything)Key terms
Section titled “Key terms”| Term | What it means |
|---|---|
| Callback prop | A function passed to a child component to notify the parent of an event |
| Custom hook | A function starting with use that calls React hooks — for sharing stateful logic |
useMemo | Caches a derived value; recomputes only when dependencies change |
| Empty state | A message shown when a list is legitimately empty — not an error |
| Error Boundary | A class component that catches render errors and shows a fallback UI |
axios.isAxiosError | Type-safe check to access HTTP status and response data on a caught error |
What is next
Section titled “What is next”Module 12 — Bulletin Frontend Build and Deploy →
Module 12 is the finish line. You’ll wire the deployed Railway API URL into the frontend, set up GitHub Pages for the React build, and do a final walkthrough of the complete Bulletin app end-to-end.