Test behaviour
Test what a user can observe rather than component internals. Render the interface, find controls by accessible role or label, perform an interaction and check the resulting content. Keep pure data transformations outside components so they can also be tested as ordinary functions.
test("adds a task", async () => { render(<App />); await user.type( screen.getByLabelText("New task"), "Review Hooks" ); await user.click( screen.getByRole("button", { name: "Add task" }) ); expect( screen.getByText("Review Hooks") ).toBeInTheDocument(); });
Build for production
npm run build npm run preview
Resolve build warnings, then test the preview rather than assuming development and production behave identically. Deploy the generated dist directory to a static host, or follow your framework's deployment process. Configure the server to return the application entry point for client-side routes.
A practical workflow
Start from the data model and a static component tree. Pass props, add interaction, then place state in the nearest owner that needs it. Derive values during rendering, reserve Effects for external synchronisation and extract abstractions only after repetition reveals a useful boundary. Use the React developer tools to inspect props, state and renders when behaviour is unclear.
Where to go next
Finish the task list: add filters, editing, persistence, loading and error states, then test its main user journeys. After that, build a second project with routing and a real API. Learn a React framework when your application needs integrated routing, server rendering or production data-loading conventions, and add TypeScript when shared component and API contracts would benefit from static checking.
Final project: ship the task application
Bring the course work together into a small production-ready application.
- Create, rename, complete and delete tasks.
- Filter all, active and completed tasks.
- Persist tasks or load them from an API with clear request states.
- Use semantic HTML, visible focus and associated labels.
- Test at least the add, toggle and delete user journeys.
- Create and preview a production build.
- State has one clear owner and is never mutated.
- Keys are stable data ids.
- Derived values are calculated rather than duplicated.
- Every Effect synchronises with an external system and has appropriate cleanup.
- Components have purpose-based names and focused responsibilities.
- The browser console and production build contain no unexplained errors.
