Skip to content

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.

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.isAxiosError for API failures
  • ErrorBoundary for 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.

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)
TermWhat it means
Callback propA function passed to a child component to notify the parent of an event
Custom hookA function starting with use that calls React hooks — for sharing stateful logic
useMemoCaches a derived value; recomputes only when dependencies change
Empty stateA message shown when a list is legitimately empty — not an error
Error BoundaryA class component that catches render errors and shows a fallback UI
axios.isAxiosErrorType-safe check to access HTTP status and response data on a caught error

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.