AI 资讯
Why Your Reusable Components Keep Breaking (And How to Fix Your API Design)
Ever stared at a component library you built just three weeks ago, only to realize it's already suffocating under a mountain of boolean props like hasBadge , isCompact , and withIcon ? I ran into this exact wall recently while refactoring a set of modular landing page cards for a mixed-media client project. What started as a clean, reusable UI module quickly devolved into a brittle spaghetti monster the moment a new layout requirement dropped. Every time a client needed a tiny structural tweak—like shifting an image from top to side, or adding a secondary action tag—I found myself cracking open the core component file and risking regressions across the entire layout. The underlying problem isn't just poor planning; it's treating components like rigid black boxes instead of flexible composition primitives. Here is what that trap looks like in code: // The Trap: A monolithic component buckling under conditional props function ProductCard ({ title , price , badgeText , isLarge , hasImage , imageSrc , variant }) { return ( < div className = { `card ${ variant } ${ isLarge ? ' large ' : '' } ` } > { hasImage && < img src = { imageSrc } alt = { title } /> } { badgeText && < span className = "badge" > { badgeText } </ span > } < h3 > { title } </ h3 > < p > { price } </ p > </ div > ); } To break out of this cycle, I had to shift away from monolithic prop drilling and lean into compound component patterns—handing structural control back to the consumer while keeping styles neatly encapsulated: // The Fix: Composable layout primitives function Card ({ children , className }) { return < div className = { `card-base ${ className || '' } ` } > { children } </ div >; } Card . Header = function CardHeader ({ children }) { return < div className = "card-header" > { children } </ div >; }; Card . Body = function CardBody ({ children }) { return < div className = "card-body" > { children } </ div >; }; // Usage: Clean, extensible, and untouched core logic export default function Ap
AI 资讯
Build map guidance that follows the user without blocking pinch-to-zoom
A navigation map should help the user move through the world, not fight every gesture they make. I recently hit a deceptively simple bug while building field guidance in a React Native / Expo app: the route rendered correctly and the camera followed the current position, but users could not meaningfully zoom or pan while walking. They could pinch the map, but the next location update snapped the camera back to a fixed zoom. The map looked active. The experience felt broken. The cause: two camera owners The implementation combined two useful features: followsUserLocation={true} on the native map. animateCamera(...) after every location update, using a fixed walking zoom and pitch. Each feature was reasonable on its own. Together, they gave the camera two automatic owners and the user none. A pinch gesture changed the zoom for a fraction of a second. Then a GPS update arrived and our effect applied the navigation camera again. On iOS, native user-follow behavior added another layer of camera control. A better model: follow mode and explore mode The fix was not to stop navigation. Route progress, distance, bearing, breadcrumb recording and off-route detection should all continue regardless of what the user does with the map. Only the camera behavior should change. We now keep a small piece of local UI state: const [ cameraFollowing , setCameraFollowing ] = useState ( navigationActive ); useEffect (() => { if ( ! navigationActive || ! cameraFollowing || bearing == null ) return ; mapRef . current ?. animateCamera ( walkingCamera ( currentCoordinate , bearing ), { duration : 480 }, ); }, [ currentCoordinate , bearing , navigationActive , cameraFollowing ]); The native follow prop uses the same state: < MapView showsUserLocation followsUserLocation = { navigationActive && cameraFollowing } onTouchStart = { () => { if ( navigationActive ) setCameraFollowing ( false ); } } /> As soon as the user touches the map, the camera enters explore mode. Pinch, pan and rotation work n
AI 资讯
I Built The Most Advanced Job Application Tracker
If you're actively applying for jobs, you probably know the struggle: Did I already apply to this company? Which resume version did I send? What salary did I mention when I applied? What was the budget mentioned in the job posting? When did I apply for this one? Which interviews are scheduled this week? What were the HR contact details again? What exactly were the requirements for this role? When is my next interview? Where did I even find this posting? How many of my applications are actually turning into interviews? Every one of those is answerable. The problem is that the answers are scattered across a spreadsheet, a notes app, your inbox, and your memory — and reassembling them takes longer than the follow-up you were trying to send. Spreadsheets are where most people start, and they hold up until somewhere around application number twelve. After that, searching, filtering, and keeping the thing current becomes its own small job — and a spreadsheet still won't tell you that six applications have been sitting in "Applied" for a month, or whether your last twenty went better than the twenty before them. That's why I built HireLoop — an advanced job application tracker meant to reduce the mental load of a job search rather than add to it. Live app: hireloop.yogeshchavan.dev — free to use, with a demo account if you'd rather look around before signing in. Check out the application demo video below: Check out some preview images of the application The short version With HireLoop you can: Track every application in one place — status, dates, salary, source, and links See where your search stands at a glance on a dashboard Move applications through a Kanban pipeline Search, filter, and sort as the list grows See interviews and deadlines on a calendar Analyse interview rates, offer rates, application trends, and which sources actually work Store notes, resume versions, HR contacts, salary details, and job links per application Mark the ones that matter as favourites Kee
AI 资讯
Why Plumeria?
"CSS Modules are fine after all." If you build web interfaces for a living, you have probably said this. After wrestling with runtime CSS-in-JS configuration, chasing specificity bugs across dynamic boundaries, or watching a utility-first framework bloat your markup, returning to the humble CSS Module feels like a relief. That isn't a compromise made for lack of features. CSS Modules win because they are predictable : the CSS you write behaves exactly as written. There is no runtime parser guessing your intent, no injection-order races between chunks, and almost no runtime JavaScript — just a class mapping object. But the safety has a price. You give up TypeScript-integrated styling, compile-time validation, dynamic theming, and seamless colocation. Plumeria is designed to eliminate this compromise. It matches — and in several areas exceeds — the predictability of CSS Modules, while delivering the type-safe developer experience of a modern CSS-in-JS library. The Zero-Trace Runtime Try compiling this — note that the style is actually applied, not left unused: import * as css from ' @plumeria/core ' ; const styles = css . create ({ box : { padding : 16 , color : ' red ' } }); export const Box = () => < div classStyle = { styles . box } > Box </ div >; Here is the entire JavaScript build output: export const Box = () => < div className = { ' xqqbxt1d xq96bg3w ' } > Box </ div >; The declarations move to a generated stylesheet: .xqqbxt1d { padding : 16px ; } .xq96bg3w { color : red ; } The style still renders, yet import * as css from '@plumeria/core' and the entire css.create declaration have vanished. This is not dead-code elimination — nothing in this file is unused, and no bundler could remove a live call for you. The compiler resolves the class names statically and rewrites the call site, so the library never has a runtime form to eliminate in the first place. That disappearing import is the most concise illustration of a Zero-Trace Runtime — anything that shouldn'
AI 资讯
TypeScript Enums Are Still Controversial in 2026: Here Is When to Use Them and When to Reach for `const` Objects
TypeScript Enums Are Still Controversial in 2026: Here Is When to Use Them and When to Reach for const Objects This article was written with the assistance of AI, under human supervision and review. Most TypeScript enum debates stem from a single misunderstanding: developers treat enums as a pure type-level construct when they generate real runtime code. This disconnect creates bundle bloat, unexpected behavior at runtime, and type safety gaps that only surface in production. Teams that reach for enums by default pay a hidden cost in every build. The enum controversy persists because TypeScript enums violate a core expectation: types should disappear at compile time. Unlike interfaces or type aliases that vanish during transpilation, enums produce JavaScript objects that ship to the browser. This runtime footprint matters when bundle size directly affects load time and business metrics. The alternative pattern— const objects with as const assertions—delivers the same developer experience without the runtime overhead. When developers understand the tradeoffs, the choice becomes mechanical: use enums where their runtime behavior adds value, use const objects everywhere else. Key Takeaways TypeScript enums generate runtime JavaScript objects that increase bundle size, while const objects with as const provide the same type safety with zero runtime overhead. Numeric enums enable reverse mapping and bitwise flags, making them valuable for low-level APIs and performance-critical code where runtime lookup is required. The const enum feature eliminates runtime code but breaks module boundaries and fails with external libraries, creating maintenance hazards in shared codebases. Const objects work seamlessly with tree-shaking, module systems, and JSON serialization, making them the default choice for API contracts and configuration. Migration from enums to const objects requires runtime validation at module boundaries to preserve type safety guarantees when data enters your s
AI 资讯
React useEvent Hook: Stable Callbacks Without Stale Closures (2026)
Every React developer eventually meets the same fork in the road. You write an event handler that reads state, pass it to a child or an effect, and now you must choose: leave it as a plain inline function and watch every render create a new reference — breaking React.memo , re-running effects, re-subscribing listeners — or wrap it in useCallback and start playing dependency-array whack-a-mole, where one forgotten dependency means the handler sees state from three renders ago. That second failure mode has a name — the stale closure — and it's arguably the most common React bug in production code. The fix has a name too: useEvent , proposed in an official React RFC in 2022 , and available today as useEvent in @reactuses/core . It gives you a function whose identity never changes across renders but whose body always sees the latest state and props . Both halves of the fork, no trade-off. This post covers the API, the three-line implementation trick that makes it work, how it compares to useCallback and to React 19.2's built-in useEffectEvent , real patterns, and the one rule you must respect (don't call it during render). TypeScript-first. The Problem in Thirty Seconds Here's the bug factory. A chat component sends a heartbeat with the current draft text: function Composer ({ roomId }: { roomId : string }) { const [ draft , setDraft ] = useState ( '' ); useEffect (() => { const id = setInterval (() => { sendHeartbeat ( roomId , draft ); // ⚠️ which draft? }, 3000 ); return () => clearInterval ( id ); }, [ roomId ]); // draft intentionally omitted — we don't want to reset the timer return < textarea value = { draft } onChange = { e => setDraft ( e . target . value ) } />; } The interval closes over the draft that existed when the effect ran — the empty string. Every heartbeat sends '' forever. Add draft to the dependency array and the closure is fresh, but now the interval tears down and restarts on every keystroke . useCallback doesn't help: it has the exact same depen
AI 资讯
Project Explanation for my Chesso application
Project High-Level Summary Chesso is a full-stack, real-time multiplayer chess platform engineered to provide low-latency online gameplay. It features real-time move synchronization, authoritative backend match clocks, secure authentication using JWT and Google OAuth, and full chess rule validation. I built it using the MERN stack (MongoDB, Express, React, Node.js) combined with Socket.IO for bi-directional WebSocket communication and Chess.js for move validation and FEN (Forsyth–Edwards Notation) state management. One of the main challenges I solved was building a server-authoritative state and clock synchronization mechanism to prevent client tampering and handle mid-game reconnections gracefully. Tech Stack & Architectural Overview Frontend : React, Vite for fast builds, React for declarative UI updates upon WebSocket events. Backend API : Node.js, Express.js Event-driven, non-blocking I/O ideal for handling multiple concurrent WebSocket connections. Socket.IO : Provides bi-directional socket events, auto-reconnection fallback, and socket room abstraction. Database : MongoDB for flexible JSON-like document model ideal for storing FEN strings, match logs, and user metadata. Auth & Security : Google OAuth 2.0, Passport.js, JWT, bcryptusing standard authentication flow providing password hashing (bcrypt) and session security via JWT tokens. Implementation of matchmaking & Queueing System When a player clicks "Play", the client emits StartGame with their playerID. The server verifies turn ownership (game.currentP === playerID). The move is executed in an isolated server-side Chess() instance (gameSockets.js). If empty, the player is queued and notified via waitingForOpponent. If another player is waiting, waitingQ.shift() pairs them instantly, creates a new game record in MongoDB (GameModel.js), assigns piece colors (white/black), and joins both sockets into a dedicated Socket.IO room named after the gameID. Game Recovery & Reconnection Resilience The server exposes
AI 资讯
I built a Markdown resume builder for the AI-paste workflow — here's everything that broke
There's a workflow that basically didn't exist three years ago and now half the job-seekers I know use it: ask ChatGPT, Claude, Gemini, or any AI to write your resume bullets, get back beautifully structured text… and then spend forty minutes mangling it into Word or a drag-and-drop resume builder, fixing bullet indentation and font sizes by hand. Here's the thing that bugged me: LLMs already speak Markdown. Ask any chatbot for a resume and you get ## Experience , **Senior Engineer** , - Shipped X — clean, structured Markdown. Then every resume tool on earth makes you throw that structure away and re-enter it into form fields. So I built ResumeMD: a split-pane editor where you paste Markdown on the left, see a typeset resume on the right, pick a template, and download a PDF. No signup to start, everything in localStorage by default. This post is about the parts that fought back. Decision 1: Markdown is the source of truth Most resume builders store your resume as a proprietary JSON blob mapped to form fields. I wanted the document itself to be portable text. That means the entire product is "just" a Markdown renderer with opinions: h2 = section headers (Experience, Education) — these get the decorative treatment per template: uppercase, border, background, prefix glyphs. h3 = job titles — plain, bold, primary color. One weird trick I'm genuinely fond of: the sidebar template splits a single Markdown document into main column and sidebar using an HTML comment ( <!-- sidebar --> ) as the split marker. Content above the marker is the main column; below is the sidebar. It keeps the document valid Markdown everywhere else. The preview is react-markdown + remark-gfm with a 300ms debounce, styled by a template system that turned out to need three parallel implementations of every template: CSS classes for the live preview, inline-style functions shared between preview and template cards, and pure-JS styles for the PDF renderer. Thirty-two templates, three layers each. When
开发者
Building for the Next Wave: My Journey Crafting Next.js Templates for the Nigerian Market
Bridging Design and Code to Empower Local Businesses As a full-stack developer specializing in JavaScript and React, one of the most exciting ventures I'm currently on is building ready-made websites and Next.js templates through Softchic. This isn't just about coding; it's about deeply understanding the needs of businesses, particularly within the vibrant and rapidly evolving Nigerian market, and translating those into high-performance, beautiful web solutions. Why Next.js? Performance, SEO, and Developer Experience My choice of Next.js as the primary framework for these templates was deliberate: Performance: Server-side rendering (SSR) and static site generation (SSG) capabilities are crucial. In areas where internet speeds might vary, a fast-loading website isn't just a nice-to-have; it's essential for user retention and conversion. SEO: For businesses looking to establish a strong online presence, robust SEO capabilities out-of-the-box mean our templates provide a solid foundation for discoverability. Developer Experience: Building with Next.js allows for efficient development, leveraging the power of React while simplifying routing, data fetching, and API routes. This means faster iteration and higher quality templates. The Nigerian Market: Unique Challenges, Immense Opportunity Crafting templates specifically for the Nigerian market presents a fascinating set of considerations: Design Aesthetics: Understanding local preferences in terms of color palettes, layouts, and user flows is critical. It's not just about what looks good globally, but what resonates locally. This is where my dual role as creative director for promotional materials comes into play – applying that eye for design directly to the templates. Mobile-First Mentality: A significant portion of internet users in Nigeria access the web via mobile devices. Every template is meticulously designed with a mobile-first approach to ensure optimal responsiveness and user experience on smaller screens. Aff
AI 资讯
Opening Web Invite Links Directly in the App with Expo Router
This article is an English translation of the original Japanese article. In my club management app, I use the following invite URL for both web and iOS app: https://squad-note.com/invite/{orgId} If the app is installed, Expo Router opens the invite screen in the app. If not, the web page displays. Using Universal Links lets me share a single URL rather than splitting it into web and app versions. Expo Router File Structure I place the invite screen as a dynamic route. apps/mobile/src/app/invite/[orgId]/index.tsx The screen retrieves the orgId from the URL via useLocalSearchParams . import { useLocalSearchParams , useRouter } from " expo-router " ; export default function InviteScreen () { const { orgId } = useLocalSearchParams < { orgId : string } > (); const router = useRouter (); const { data : org , isLoading } = api . organization . getPublic . useQuery ( { id : orgId ! }, { enabled : !! orgId }, ); // Display invite content and execute join process } When opened with /invite/abc , orgId receives abc . I also provide a page with the same path on the web side. Setting a Custom Scheme To handle app-specific URLs, I set a scheme in the Expo config. export default ({ config }: ConfigContext ): ExpoConfig => ({ ... config , scheme : " squadnote " , }); This allows handling URLs like the following during development and authentication callbacks: squadnote://invite/abc However, I use HTTPS for the invite URLs shared with users. Because custom schemes can be declared by different apps with the same scheme, I use Universal Links as the entry point to securely associate normal web URLs with the app. iOS Associated Domains In app.config.ts , I separate domains for production and development. ios : { bundleIdentifier : IS_PROD ? " com.squadnote.app " : " com.squadnote.app.dev " , associatedDomains : IS_PROD ? [ " applinks:squad-note.com " ] : [ " applinks:dev.squad-note.com " ], } Adding the configuration alone does not make it work. I also serve apple-app-site-association
AI 资讯
How I cut my Chromatic bill 10x (works on any visual testing tool)
I have been a huge Storybook and Chromatic fan for years. But at some point the bill got my attention, and when I looked into why, the fix turned out to be simple. This is the write-up of what I changed. It works on any per-snapshot tool, not just Chromatic. First, some backstory on how I got here, because it explains why the cost crept up in the first place. How I ended up paying for a lot of snapshots In the past I would build a gigantic end-to-end pipeline that was flaky as hell and made me spend time every week fixing it. It took 40 minutes to run, and when it went red someone would assume it was just flaky, merge the change anyway, and then find out it truly did break the system. So I stopped writing lots of E2Es and moved to Storybook for interaction and visual testing. Much better. But because I was rendering every state of every component as its own story to get the screenshots in place, I was generating a lot of screenshots. And every snapshot tool, Chromatic, Percy, Playwright screenshots, UI Verify, renders and bills per story. So the number of stories is the cost, and it is also the noise surface: more stories means more places for a diff to flake. I ended up paying a lot, which made me think about whether there were ways to optimise it. There were. Here they are. The core idea: combine states into one story The naive pattern is one story per variant times state times theme. A component with 5 sizes, 3 states, and 2 themes is 30 snapshots the naive way. The whole idea below is to collapse that matrix into a handful of stories while keeping full coverage. Move 1: one gallery story, not N stories For something like a Button, there is no need to have separate Primary, Secondary, and Tertiary stories. I prefer one AllVariants story that maps through the prop combinations and renders them in a grid. One snapshot then covers the entire matrix. As a bonus you get a nice grid that shows every permutation at a glance, with no extra clicks to see the variations. /
AI 资讯
React 19's useOptimistic Fixed My Instant UI. Then Combining It With useActionState Broke My Reset Button
Part 1 was about waiting well. This one is about not waiting at all, and about a couple of mistakes I...
AI 资讯
TypeScript `asserts` and Type Predicates in 2026: Writing Guards That Actually Narrow Correctly
TypeScript asserts and Type Predicates in 2026: Writing Guards That Actually Narrow Correctly This article was written with the assistance of AI, under human supervision and review. Most TypeScript runtime validation breaks down because engineers write guards that compile but don't actually narrow types where it matters. The pattern that teams overlook is the distinction between type predicates that return boolean values and assertion functions that throw on failure—and choosing the wrong one creates silent bugs that surface in production. The problem starts when developers write a function like isUser(value: unknown): boolean and expect TypeScript to understand what that boolean means. The compiler sees the function return true but has no idea that value is now safe to treat as a User type. Code that looks validated crashes at runtime because the type system never learned what the validation actually proved. The fix is adding the type predicate syntax value is User to the return signature. This tells TypeScript that when the function returns true , the narrowed type holds in the calling scope. For throwing guards that never return on failure, the asserts keyword encodes that guarantee into the signature itself. That distinction is critical. Type predicates return booleans and enable conditional narrowing. Assertion functions throw errors and narrow the remainder of the scope unconditionally. Mixing them up or using neither creates validation theater—code that runs checks but provides zero type safety. Key Takeaways Type predicates ( value is Type ) narrow types conditionally when the guard returns true , while assertion functions ( asserts value is Type ) narrow unconditionally by throwing on failure. Most guard functions fail to narrow because they return boolean instead of using predicate syntax—the compiler cannot infer type information from a plain boolean. Assertion functions are superior for null checks and invariants that should never fail, while type predic
开发者
I made a web framework
Hi everyone! I made an SSR web framework on NPM named Authtics Host (or HostJS ) About Based on tests, it starts the server in under 1 second. For a user to see the page, it takes 1-4 seconds. It also has a Developer Panel , which has controls to control the website (e.g., Restart, Shutdown and Pause Users) with DAT ( Developer Access Token ) authorization for the Developer Panel. The framework's Developer Panel has console and network tabs, where devs can see: what the page is receiving, sending or what logs it's placing in the console. Better than importing a package and setting it up on mobile. 3 Reasons why I made this Most frameworks start in 2-5+ seconds There isn't any console or network tab for mobile If there's a developer panel in another framework, it might not be mobile-friendly Package The NPM package is at: @bananacool467/authtics-host Code snippet For starting the server: (Backend script) import { App } from " @bananacool467/authtics-host " ; const app = new App (); (Bash script) node --experimental-strip-types index.ts How I got it to start in under 1 second What I did was make it do fast stuff, when it starts, it: Loads modules (node:fs, node:http, jiti) Then it loads the jiti config file Then it starts the server with the config
AI 资讯
React Concurrent Rendering: Scheduling, Interruptions, and Debugging Suspense Boundaries
You know that moment when your React Suspense fallback jumps on the screen, then disappears, then reappears, leaving you wondering if you did something wrong? I’ve been there , seeing flickers, multiple loading spinners, or even UI glitches around Suspense felt like chasing ghosts. Turns out, React’s concurrent rendering scheduler is doing a lot behind the scenes , juggling priorities, pausing work, and restarting it , and Suspense boundaries are right in the middle of this dance. Understanding how React schedules work and handles interruptions can save you hours of frustration. React’s concurrent rendering scheduler: what’s it really doing? React’s concurrent mode isn’t just a fancy name; it means React doesn’t blindly render your entire component tree all at once. Instead, it breaks rendering work into chunks and spreads it out over multiple frames. This keeps your app responsive to user input and other high-priority tasks. Imagine you’re painting a huge mural. Instead of finishing it in one go (blocking everything else), you paint a little, step back, listen if someone calls you, then paint some more. React’s scheduler works similarly: Units of work : React slices rendering into small units it can pause and resume. Priorities : Some updates are more urgent , like responding to a click , so they jump ahead. Interruptions : If something more important comes up, React pauses current work and switches. This model makes React apps feel snappy even when doing heavy rendering or fetching data. What happens when Suspense enters the scene? Suspense boundaries are React’s way to say, “Hey, if this component isn’t ready yet (because it’s waiting on data, code, or something else), show this fallback for now.” Under the hood, when a component suspends (throws a Promise), React marks that unit of work as "waiting," and the Suspense boundary kicks in to show the fallback UI immediately. But here’s the catch: React keeps trying to finish rendering the suspended component in the
AI 资讯
React Mastery Series – Day 24: React Forms – Controlled Components, Validation & React Hook Form
Welcome back to the React Mastery Series ! In the previous article, we learned how React applications communicate with backend services using Fetch API and Axios , along with best practices like service layers, interceptors, and error handling. Today, we'll explore one of the most common features you'll build as a React developer: Forms in React Whether it's: User Login Registration Profile Update Payment Details Contact Forms Search Filters Forms are everywhere. Learning how to build performant, scalable, and validated forms is an essential skill for every React developer. Understanding Forms in React A form is a collection of input elements used to collect user data. Example: Login Form Email,Password and Login Button React provides multiple ways to manage form data. The two most common approaches are: Controlled Components Uncontrolled Components Controlled Components In a controlled component, React controls the input value through state. Example: import { useState } from " react " ; function Login () { const [ email , setEmail ] = useState ( "" ); return ( < input type = "email" value = { email } onChange = { ( e ) => setEmail ( e . target . value ) } /> ); } Flow: User Types ↓ onChange ↓ React State ↓ Input Updates The input value always comes from React state. Why Controlled Components? Benefits: Easy validation Easy formatting Predictable state Better debugging Example: if ( email . length < 5 ) { // Show validation message } Since the value is stored in state, validation becomes straightforward. Uncontrolled Components In uncontrolled components, the DOM manages the input value. React accesses it using a ref. Example: import { useRef } from " react " ; function Login () { const emailRef = useRef < HTMLInputElement > ( null ); function handleSubmit () { console . log ( emailRef . current ?. value ); } return ( <> < input ref = { emailRef } /> < button onClick = { handleSubmit } > Login </ button > </> ); } Use uncontrolled components when you don't need Reac
AI 资讯
30 technical interview questions, explained the way you'd actually say them
30 Technical Interview Questions You Should Be Able to Explain Out Loud (JS / React / Node) Most interview prep content gives you a definition. Real interviews test something different: can you explain your reasoning clearly, out loud, under a little pressure — not just recite the right words. I put together 30 questions across JavaScript, React, and Node.js. Every answer here is written the way you'd actually say it in an interview, not the way a textbook would write it. How to actually use this: cover the answer, try explaining it out loud in under 30 seconds, then read the answer. If you froze or rambled, that's the real signal — more than whether you technically knew the concept. JavaScript Fundamentals 1. What's a closure, and why does it actually matter in real code? A closure is a function that remembers the variables from where it was created, even after that outer function has finished running. It powers private variables, debouncing, memoization, and module patterns. 2. setTimeout(fn, 0) vs Promise.then() — which runs first? The Promise wins. .then() callbacks go into the microtask queue, which fully drains before the next macrotask (like setTimeout ) runs — even with a 0ms delay. 3. Why does var break inside loops with closures, but let doesn't? var is function-scoped — every iteration shares the same variable. let is block-scoped, so each iteration gets its own fresh binding. 4. Where does == actually give you a different (and wrong) answer than === ? == does type coercion first — 0 == false and '' == 0 are both true. === compares type and value directly, no surprises. 5. Why does this break in callbacks with regular functions, but not arrow functions? Regular functions get this based on how they're called. Arrow functions inherit this lexically from where they were defined, so it stays consistent no matter how they're invoked. 6. If a property isn't on an object, where does JS look next? JS walks the prototype chain — the object, then its prototype, the
AI 资讯
Deploying fully static Next.js websites on Vercel
Static site generation has a branding problem. Say "static site" and people picture a blog with twelve posts and a contact form. So how far can you actually push it before you need a backend? Further than most people assume. This is a walkthrough of a production site that has no database, no API layer, no user accounts and no server-side state, and still ships 232 prerendered pages with per-user results, shareable links and dynamic social cards. The site is a Spanish political test with nine ideological axes, seventeen parties, fifty-four questions. It is in Spanish, but nothing here depends on reading it. Treat it as the reference implementation. The architecture in one sentence Three data files are the source of truth, everything else is derived at build time, and everything user-specific happens in the browser. That is the whole trick. The rest is consequences. 1. Derive pages, don't author them The site has 232 URLs. Almost none of them were written by hand. There are three data modules: the axes, the parties, and the questions. From those, generateStaticParams produces every content route: // app/ejes/[id]/page.tsx export function generateStaticParams () { return AXES . map (( a ) => ({ id : a . id })) } The interesting one is the comparison pages. Seventeen parties means 17 × 16 / 2 = 136 unique pairs, and each pair gets its own page, its own metadata and its own canonical URL: export function allPairs () { const out = [] for ( let i = 0 ; i < PARTIES . length ; i ++ ) for ( let j = i + 1 ; j < PARTIES . length ; j ++ ) out . push ({ a : PARTIES [ i ]. id , b : PARTIES [ j ]. id }) return out } export function generateStaticParams () { return allPairs (). map (( p ) => ({ pair : pairSlug ( p . a , p . b ) })) } 136 pages from twelve lines. And because the page body is computed from the same vectors, recalibrating one party silently rewrites the sixteen pages that involve it . No CMS, no migration, no content drift. The numbers on the page cannot disagree with
AI 资讯
This Article describe how u can Add Item in your data base from client
React TypeScript Property Form Validation export interface PropertyForm { propertyTitle : string ; description : string ; amenities : string ; monthlyRent : string ; location : string ; unitsAvailable : string ; applicationDeadline : string ; } export interface PropertyFormErrors { propertyTitle ?: string ; description ?: string ; amenities ?: string ; monthlyRent ?: string ; location ?: string ; unitsAvailable ?: string ; applicationDeadline ?: string ; } export const validatePropertyField = ( name : keyof PropertyForm , value : string ): string => { switch ( name ) { case " propertyTitle " : if ( ! value . trim ()) { return " Property title is required " ; } if ( value . trim (). length < 3 ) { return " Property title must be at least 3 characters " ; } return "" ; case " description " : if ( ! value . trim ()) { return " Description is required " ; } if ( value . trim (). length > 2000 ) { return " Description cannot exceed 2000 characters " ; } return "" ; case " amenities " : if ( ! value . trim ()) { return " Amenities are required " ; } return "" ; case " monthlyRent " : if ( ! value . trim ()) { return " Monthly rent is required " ; } if ( Number ( value ) <= 0 ) { return " Monthly rent must be greater than 0 " ; } return "" ; case " location " : if ( ! value . trim ()) { return " Location is required " ; } return "" ; case " unitsAvailable " : if ( ! value . trim ()) { return " Units available is required " ; } if ( ! Number . isInteger ( Number ( value ))) { return " Units available must be a whole number " ; } if ( Number ( value ) < 1 ) { return " At least 1 unit must be available " ; } return "" ; case " applicationDeadline " : if ( ! value ) { return " Application deadline is required " ; } return "" ; default : return "" ; } }; export const validatePropertyForm = ( formData : PropertyForm ): PropertyFormErrors => { const errors : PropertyFormErrors = {}; Object . entries ( formData ). forEach (([ name , value ]) => { const error = validatePropertyFiel
AI 资讯
React Mastery Series – Day 19: Routing in React – Building Single Page Applications with React Router
Welcome back to the React Mastery Series ! In the previous article, we explored Custom Hooks in React and learned how reusable logic helps developers build scalable and maintainable applications. Today, we will explore one of the most important concepts in modern frontend development: React Routing Almost every real-world React application contains multiple screens: Login Dashboard Profile Settings Reports Transactions Admin panels But React applications are usually built as: Single Page Applications (SPA) So how do we navigate between different pages without refreshing the browser? The answer is React Router What is Client-Side Routing? Traditional websites work like this: User Clicks Link | ↓ Browser Requests New HTML Page | ↓ Server Sends Page | ↓ Browser Reloads Every navigation causes a full page refresh. React Single Page Applications work differently: User Clicks Link | ↓ React Router Intercepts Request | ↓ URL Changes | ↓ React Loads Component | ↓ No Page Refresh This creates a smooth application experience. What is React Router? React Router is a library that enables navigation between different components based on the URL. Example: /login /dashboard /profile /settings Each URL maps to a React component. Example: /login | ↓ Login Component /dashboard | ↓ Dashboard Component Installing React Router For a React application: npm install react-router-dom The package provides: BrowserRouter Routes Route Link Navigate useNavigate useParams Setting Up BrowserRouter The first step is wrapping your application. Example: import { BrowserRouter } from " react-router-dom " ; import App from " ./App " ; ReactDOM . createRoot ( document . getElementById ( " root " )). render ( < BrowserRouter > < App /> </ BrowserRouter >, ); Now React can manage browser navigation. Creating Routes Routes define which component should display for a URL. Example: import { Routes , Route } from " react-router-dom " ; function App () { return ( < Routes > < Route path = "/" element = { < Ho