Nhat ky hoc tap
Ghi chep hang ngay va hang tuan ve nhung gi toi hoc, xay dung va kham pha. Ghi chu tho tu tren chien truong.
Spent the morning working through generic constraints and conditional types. The moment it clicked was when I realized generics are just function parameters for types. Built a type-safe API client that infers response types from the endpoint string. Feeling powerful.
Key takeaway: `T extends keyof SomeMap` is basically a type-level filter. Once you see it that way, mapped types and conditional types follow naturally.
Read through several articles on clean architecture applied to React/Next.js projects. The core idea: separate your business logic from your framework code. Created a `/lib` layer for pure business functions and a `/hooks` layer that bridges React with business logic.
Also started organizing by feature instead of by type. Instead of `/components`, `/hooks`, `/utils` at the top level, I'm now grouping by domain: `/features/auth`, `/features/projects`, etc.
Explored TypeScript utility types: Partial, Pick, Omit, Record, Extract, Exclude. These are incredibly useful for deriving types from existing ones without duplication. Used `Pick<User, 'name' | 'email'>` for a profile update form instead of creating a separate interface.
Also discovered `satisfies` operator. It validates that an expression matches a type without widening it. Game changer for config objects.
Deep dive into the mental model behind React Server Components in Next.js 13+. The boundary between server and client is the key insight. Server components can fetch data directly, reduce bundle size, and run code that should never reach the client.
Rule of thumb: start with server components. Only add 'use client' when you need interactivity (state, effects, event handlers, browser APIs).
Started building this Build in Public site using Next.js App Router. Chose a minimal design with a sidebar layout for desktop and bottom nav for mobile. Using shadcn/ui for consistent components and Tailwind for styling.
The file-based routing in App Router is intuitive. Each folder becomes a route segment, and `page.tsx` is the entry point. Layout nesting is automatic and elegant.
Replaced Context API with Zustand in the weather dashboard app. The API is dead simple: create a store with `create()`, use it like a hook. No providers, no boilerplate. Performance is better too since components only re-render when their selected state changes.
Migration took about 30 minutes for the entire app. Zustand is now my go-to for client state.
Integrated React Query (TanStack Query) into the weather dashboard. Server state management is fundamentally different from client state. React Query handles caching, background refetching, stale data, and error states out of the box.
Before: manual loading states, error handling, cache invalidation. After: `useQuery` and `useMutation`. The stale-while-revalidate pattern makes the UX feel instant.
Created my first set of custom hooks: `useLocalStorage`, `useDebounce`, `useMediaQuery`. The pattern is simple but powerful. Extract stateful logic into a reusable function prefixed with `use`.
The `useDebounce` hook was particularly satisfying. It takes a value and delay, returns the debounced value. Used it for the search input in the weather app to avoid firing API calls on every keystroke.
Finished the weather dashboard project. Features: city search with autocomplete, current conditions display, 5-day forecast chart, and a saved locations list with localStorage persistence. Used the OpenWeather API.
Learned a lot about managing async state in React. The combination of `useState` + `useEffect` for data fetching works but gets messy. Looking forward to learning React Query next week.
Studied compound components, render props, and the children pattern in React. The compound component pattern (like how Radix UI works) is elegant. Parent manages state, children consume it through context. The API feels natural.
Built a custom Accordion component using this pattern. The usage looks clean: `<Accordion><Accordion.Item><Accordion.Trigger /><Accordion.Content /></Accordion.Item></Accordion>`.
Wrote my first proper unit tests. Started with pure utility functions since they're the easiest to test. The arrange-act-assert pattern is straightforward. Testing gave me immediate confidence that my date formatting and validation functions work correctly.
Next step: testing React components with React Testing Library.
Converted the task manager app from JavaScript to TypeScript. The process was gradual: rename `.js` to `.ts`, fix type errors, add interfaces for data structures. TypeScript caught 3 actual bugs during migration. One was a property access on a potentially undefined object.
The DX improvement is significant. Autocomplete, inline documentation, and compile-time error checking make coding faster, not slower.
Researched error handling patterns in JavaScript. Key insight: use custom error classes for domain-specific errors, try-catch for async boundaries, and Error Boundaries in React for UI recovery.
Created a `Result` type inspired by Rust: `type Result<T, E> = { ok: true; value: T } | { ok: false; error: E }`. Forces explicit error handling at call sites.
Spent the day understanding the event loop, microtasks vs macrotasks, and how Promises actually work under the hood. Drew diagrams of the call stack, task queue, and microtask queue. The mental model is now solid.
`async/await` is syntactic sugar over Promises, which are syntactic sugar over callbacks. Understanding the layers makes debugging async code much easier.
Completed the vanilla JavaScript task manager. Features: add/edit/delete tasks, drag-and-drop reordering, localStorage persistence, filter by status, and keyboard shortcuts.
Built everything without a framework to understand the fundamentals. Manual DOM manipulation is tedious but educational. Now I truly appreciate what React does.
Closures are functions that remember their lexical scope. The module pattern uses closures to create private state. Before ES modules, this was the primary way to organize JavaScript code.
Wrote a counter module, a pub/sub system, and a simple state manager all using closures. The pattern is everywhere in JavaScript.
After initial resistance, Tailwind CSS clicked today. The utility-first approach is fast once you internalize the class naming convention. `flex items-center justify-between gap-4` reads like a sentence describing layout intent.
Key productivity tip: use the Tailwind CSS IntelliSense VS Code extension. Autocomplete and class sorting save significant time.
Learned CSS transitions and keyframe animations. Transitions handle simple state changes (hover, focus). Keyframes handle complex multi-step animations. The `animation` shorthand combines name, duration, timing, delay, iteration, and direction.
Built a loading spinner, a slide-in sidebar, and a staggered list animation. Performance tip: only animate `transform` and `opacity` for smooth 60fps.
Grid layout handles 2D layouts that Flexbox can't. `grid-template-columns: repeat(auto-fill, minmax(300px, 1fr))` creates a responsive grid without media queries. Named grid areas make complex layouts readable.
Built a dashboard layout with header, sidebar, main content, and footer using CSS Grid. The `grid-area` property with named templates is incredibly intuitive.
Flexbox handles 1D layouts (row or column). The most useful patterns: centering with `items-center justify-center`, space-between for navbars, `flex-1` for fill remaining space, and `flex-wrap` for responsive card grids.
Key insight: `flex-shrink: 0` prevents items from collapsing. Essential for fixed-width sidebar layouts.
Spent time learning about semantic HTML elements: `main`, `article`, `section`, `nav`, `aside`, `header`, `footer`, `figure`, `time`. Using semantic elements improves accessibility, SEO, and code readability.
`<article>` is for self-contained content. `<section>` is for thematic grouping. `<aside>` is for tangentially related content. Choosing the right element communicates intent to browsers and screen readers.
Configured VS Code with essential extensions: ESLint, Prettier, Tailwind CSS IntelliSense, GitLens. Set up a consistent terminal workflow with Git aliases.
Also established a learning routine: 2 hours of focused study in the morning, 2 hours of project work in the afternoon, 30 minutes of writing/reflection in the evening.
Decided to document this entire learning journey publicly. Reasons: accountability, building a portfolio of work and thinking, connecting with others on the same path, and forcing myself to articulate what I learn.
The plan: 12 weeks, structured roadmap, daily logs, weekly notes, and shipped projects. Everything open and transparent.
Created the 12-week learning roadmap. The structure: weeks 1-2 on HTML/CSS, weeks 3-4 on JavaScript, weeks 5-6 on React, weeks 7-8 on Next.js & TypeScript, weeks 9-10 on backend & databases, weeks 11-12 on DevOps & deployment.
Each week has clear goals, recommended resources, and a project to build. The roadmap is ambitious but achievable with consistent daily effort.