Tillbaka till Utvecklare
Frontend-utveckling
Frontend-intervjufrågor — React, TypeScript och webbläsaren.
Vad är skillnaden mellan Component och PureComponent i React? Ge ett exempel där PureComponent kan orsaka problem i en app.
Component renderar om varje gång setState anropas eller föräldern renderar om, oavsett om props/state faktiskt ändrats. PureComponent implementerar shouldComponentUpdate med en ytlig (shallow) jämförelse av props och state och hoppar över omrendering om referenserna inte ändrats. Det kan orsaka problem när man muterar objekt eller arrayer direkt (t.ex. push till en array utan att skapa en ny referens): PureComponent upptäcker inte ändringen och UI:t blir inaktuellt.
Varför kan det vara farligt att kombinera React Context med shouldComponentUpdate?
shouldComponentUpdate (eller PureComponent) kan blockera omrendering av mellanliggande komponenter i trädet. Om ett kontextvärde ändras men en förfader returnerar false från shouldComponentUpdate, kommer dess barn inte att renderas om trots att de konsumerar det kontextet. Det innebär att context-konsumenter kan visa inaktuell data. Det moderna Context API:t (React 16.3+) mildrar detta genom att propagera direkt till konsumenter, men det äldre context-systemet var helt sårbart för detta.
Beskriv tre sätt att skicka information från en barnkomponent till dess förälder i React.
1) Callback-props – föräldern skickar en funktion som prop; barnet anropar den med data. 2) Lyfta state / delat context – flytta state till föräldern (eller en gemensam context-provider) och låt båda komponenterna komma åt det. 3) Refs – föräldern skapar en ref (useRef / React.createRef) och skickar den till barnet; barnet kan exponera imperativa metoder (useImperativeHandle) eller föräldern läser DOM-värden direkt.
Ge två sätt att förhindra att en React-komponent renderas om i onödan.
1) React.memo (för funktionskomponenter) eller PureComponent (för klasskomponenter) – omsluter komponenten så att den bara renderas om när dess props ändras vid ytlig jämförelse. 2) useMemo / useCallback – memoiserar dyra beräkningar eller callback-referenser så att nedströmskomponenter som tar emot dem som props inte ser nya referenser vid varje render och därmed hoppar över omrendering.
Vad är ett React Fragment och varför behöver vi det? Ge ett exempel där det kan orsaka problem i en app.
Ett Fragment (<React.Fragment> eller <> </>) låter dig gruppera flera element utan att lägga till en extra DOM-nod. Det behövs eftersom JSX-uttryck måste returnera ett enda rotelement. Det kan orsaka problem om du förlitar dig på direkta förälder-barn-DOM-relationer för CSS (t.ex. Flexbox eller Grid) – ersätter man en omslutande <div> med ett Fragment försvinner containern och barnen hamnar direkt under farföräldern, vilket bryter den avsedda layouten.
Ge tre exempel på Higher-Order Component (HOC)-mönstret i React.
1) withRouter (React Router) – injicerar route-props (history, location, match) i den omslutna komponenten. 2) connect (Redux) – mappar store-state och dispatch till komponentens props. 3) En anpassad withAuth-HOC som kontrollerar autentisering och antingen renderar den omslutna komponenten eller omdirigerar till inloggningssidan. HOC:ar tar emot en komponent och returnerar en ny förbättrad komponent, vilket främjar återanvändning av tvärsgående logik.
Hur många argument tar setState i React och varför är det asynkront?
setState tar upp till två argument: 1) en uppdaterare – antingen ett objekt som shallow-mergas in i state, eller en funktion (prevState, props) => newState för uppdateringar som beror på nuvarande state; 2) en valfri callback som körs efter att state har applicerats och komponenten har renderats om. Det är asynkront (batchat) av prestandaskäl: React grupperar flera setState-anrop i ett enda omrenderingspass för att undvika onödiga mellanliggande renderingar och layout thrashing.
Vilka steg behövs för att migrera en React Class Component till en Function Component?
1) Ersätt klassdeklarationen med en funktion som tar props som argument. 2) Ta bort konstruktorn; konvertera this.state till useState-hooks. 3) Ersätt livscykelmetoder (componentDidMount, componentDidUpdate, componentWillUnmount) med useEffect-hooks. 4) Ta bort alla referenser till 'this'. 5) Konvertera klassmetoder till lokala funktioner eller använd useCallback. 6) Ersätt this.props med destrukturerad props-parameter. 7) Om context används, byt static contextType mot useContext. 8) Om refs används, ersätt createRef med useRef.
Lista några sätt att använda stilar med React-komponenter.
1) Inline-stilar via style-propen (ett JS-objekt med camelCase-egenskaper). 2) CSS/SCSS-filer som importeras direkt i komponentfilen. 3) CSS Modules (lokalt scopade klassnamn via *.module.css). 4) CSS-in-JS-bibliotek (styled-components, Emotion) som genererar scopade stilar vid körning. 5) Utility-first-ramverk som Tailwind CSS som appliceras via className-strängar.
Hur renderar man en HTML-sträng från servern i React?
Använd propen dangerouslySetInnerHTML: <div dangerouslySetInnerHTML={{ __html: htmlString }} />. Namnet är avsiktligt varnande eftersom att injicera rå HTML är en XSS-risk. Sanera alltid strängen på serversidan eller med ett pålitligt bibliotek (t.ex. DOMPurify) innan rendering. Alternativt kan man parsa HTML:en till ett React-elementträd med ett bibliotek som html-react-parser om man behöver kontroll på komponentnivå.
Hur skulle du implementera textmarkering av matchande tecken i en React-autocomplete-komponent?
Dela upp förslagstexten i delar baserat på sökfrågan med en skiftlägesokänslig regex eller strängindexmatchning. Rendera icke-matchande delar som vanlig text och omslut matchande delsträngar i en <mark> eller <span> med en highlight-CSS-klass. Till exempel: text.split(new RegExp(
(${escapad query}), 'gi')).map(part => matchar ? <strong>{part}</strong> : part). Se till att escapa regex-specialtecken i frågan.Vilka edge cases bör du hantera i en React autocomplete-komponent för en perfekt användarupplevelse?
Viktiga edge cases inkluderar: debouncing av input för att undvika överdrivna API-anrop, hantera tomma resultat elegant, tangentbordsnavigering (piltangenter, Enter, Escape), stänga dropdown vid blur/klick utanför, hantera snabb skrivning som orsakar asynkrona svar i fel ordning (race conditions), trimma blanksteg, visa laddningsindikator, förhindra formulärinskickning med Enter vid val, och tillgänglighet (ARIA-attribut, skärmläsarmeddelanden).
Varför bör datafiltreringsfunktionen i en autocomplete-komponent vara asynkron även när man använder lokal mockdata?
Att göra filterfunktionen asynkron simulerar verkliga förhållanden där data kommer från en nätverksbegäran med latens. Det tvingar dig att hantera laddningstillstånd, race conditions (inaktuella svar som anländer efter nyare frågor) och avmontering av komponenten under pågående begäran. Det gör också komponenten redo att byta mockdata mot ett riktigt API utan arkitekturändringar.
Hur kan du hantera race conditions i en React autocomplete som hämtar förslag asynkront?
Använd en rensningsmetod så att bara det senaste svaret tillämpas. I en useEffect, returnera en cleanup-funktion som sätter en cancelled-flagga; när det asynkrona svaret anländer, kontrollera flaggan innan state uppdateras. Alternativt kan du använda en AbortController för att avbryta tidigare fetch-anrop, eller ha en räknare för begäran-ID och bara tillämpa resultat vars ID matchar den senast skickade begäran.
Varför kräver React att man bara använder funktionella komponenter med hooks för moderna komponenter?
Funktionella komponenter med hooks ger en enklare mental modell: inga 'this'-bindningsproblem, renare separation of concerns via custom hooks, enklare testning och bättre anpassning till Reacts concurrent-funktioner. Hooks som useState, useEffect, useRef och useMemo täcker alla klasslivscykelmönster på ett komponerbart sätt. React-teamet rekommenderar hooks för all ny kod eftersom de minskar boilerplate och uppmuntrar logikåteranvändning utan HOC:ar eller render props.
Hur hanterar du API-fel på ett elegant sätt i ett React-gränssnitt?
Omslut fetch/axios-anropet i ett try-catch-block och upprätthåll en felstatevariabel. Om förfrågan misslyckas eller returnerar en icke-2xx-status, sätt felstaten och rendera ett användarvänligt felmeddelande istället för resultaten. Inaktivera också skicka-knappen eller visa en laddningsindikator medan förfrågan pågår.
Vilka är de viktigaste övervägandena för att göra ett datainmatningsformulär responsivt och användarvänligt i React?
Använd kontrollerade komponenter så att formulärets tillstånd alltid återspeglar gränssnittet, tillhandahåll tydliga etiketter och platshållartext, ge omedelbar valideringsåterkoppling och hantera laddnings- och feltillstånd med synliga indikatorer. För matrisinmatning gör ett textarea med monospace-teckensnitt rutnätet lättare att läsa.
Hur implementerar man rollbaserade skyddade rutter i en React SPA utan en riktig backend?
Man håller ett simulerat autentiseringstillstånd (t.ex. i React Context eller ett globalt store, persisterat i sessionStorage/localStorage) som lagrar den valda rollen. En
ProtectedRoute-komponent kontrollerar aktuell roll; om den saknas omdirigeras användaren till inloggningssidan via <Navigate>. Varje rutträd (/taller/..., /cliente/...) omsluts av sin egen guard så att direkt URL-åtkomst alltid stoppas.Vad är Container/Presenter-mönstret i React och varför är det värdefullt?
Container-komponenter (smarta) äger tillstånd och affärslogik och skickar data neråt via props. Presenter-komponenter (dumma) är rena renderingsenheter utan sidoeffekter. Uppdelningen förbättrar testbarhet (presenters är enkla att enhetstesta), återanvändbarhet och läsbarhet eftersom UI-logik är helt separerad från domänlogik.
Hur implementerar man en ändlig tillståndsmaskin för ett orders livscykel i React?
Definiera en karta över tillåtna övergångar (t.ex.
{ CREATED: ['DIAGNOSED','CANCELLED'], DIAGNOSED: ['AUTHORIZED','CANCELLED'], ... }). Exponera en transition(order, newStatus)-funktion i en ren domänmodul som validerar övergången mot kartan, lägger till en Event-post och returnerar ett nytt orderobjekt. React-tillståndet uppdateras genom att byta ut ordern i arrayen; UI:n härleder vilka åtgärdsknappar som ska visas från det aktuella statusvärdet.Hur håller man React-tillstånd och localStorage tillförlitligt synkroniserade?
Använd en anpassad hook (t.ex.
useLocalStorage) som initierar tillståndet genom att läsa från localStorage och omsluter settern så att varje uppdatering även anropar localStorage.setItem. För komplexa objektgrafer serialiseras med JSON.stringify/JSON.parse. Standarddata seedas en gång vid första laddning genom att kontrollera om nyckeln saknas. Mönstret säkerställer att en siduppdatering alltid hydrerar korrekt tillstånd.Hur tillämpar man SOLID:s Open/Closed-princip när man lägger till nya orderstatus eller affärsregler i ett React-frontend?
Håll varje affärsregel i sin egen funktion eller klass i ett domänlager (t.ex.
src/domain/orders/). Att lägga till en ny status eller regel innebär att man lägger till en ny post i övergångskartan och en ny valideringsfunktion — befintliga funktioner rörs inte. UI-komponenter konsumerar bara domän-API:t och behöver därför heller inga ändringar. Detta undviker att modifiera beprövad kod och begränsar påverkan av nya krav.Vad innebär 'hexagonal arkitektur tillämpad på frontend' i praktiken?
Domänlagret (ren affärslogik, inga React-importer) ligger i centrum. Adaptrar omger det: UI-adaptrar är React-komponenter och hooks som anropar domänfunktioner; persistensadaptrar är moduler som läser/skriver till localStorage. Domänen importerar aldrig från React eller localStorage — den arbetar bara med ren data. Detta gör domänen oberoende testbar och lätt att byta ut (t.ex. ersätta localStorage med IndexedDB utan att röra affärsreglerna).
Hur hanterar och visar man affärsregelöverträdelser (t.ex. NO_SERVICES, REQUIRES_REAUTH) i ett React UI utan att krascha applikationen?
Affärsregelöverträdelser bör returneras som typade felobjekt från domänfunktioner istället för att kastas som undantag. Den anropande hooken eller reducern lägger till dem i en
errors-array på ordern och uppdaterar UI-tillståndet. Komponenter renderar en fellista eller toast baserat på den arrayen. Eftersom exekveringen fortsätter normalt kraschar appen aldrig; felen är en del av domänmodellen och syns i orderns historik.Hur implementerar man ett oföränderligt händelse-/revisionslogg för domänentiteter i en frontend-applikation?
Varje mutation producerar en ny Event-post (med id, type, fromStatus, toStatus, timestamp) och lägger till den i orderns
events-array. Arrayen modifieras aldrig på plats; istället returneras och lagras ett nytt orderobjekt med den utökade händelselistan. Detta skapar ett fullständigt, kronologiskt protokoll över vad som hänt med ordern som både verkstaden och kunden kan granska, och det är trivialt att testa eftersom loggen är ren data.Vad är mobile-first-design och hur påverkar det CSS- och komponentbeslut i ett React-projekt?
Mobile-first innebär att man skriver basistilar för den minsta viewporten och lägger till överskridningar för större skärmar med
min-width media queries. I React påverkar detta layoutval (flexbox-stackar istället för grids för mobil, progressiv disclosure för tät data), tabellhantering (kollapsa till kortlistor på små skärmar) och navigationsmönster (flikar längst ned eller hamburgarmenyer istället för sidopaneler). Att börja smalt tvingar fram prioritering av de viktigaste UI-elementen.Hur implementerar man den 110%-kostnadsöverskridningsgarden som en återanvändbar, testbar funktion i domänlagret?
Skriv en ren funktion
checkCostOverrun(order): BusinessError | null som beräknar limit = order.authorizedAmount * 1.10 och jämför det med order.realTotal. Om realTotal > limit returneras ett REQUIRES_REAUTH-felobjekt; annars returneras null. Funktionen anropas efter varje kostnadsuppdatering och vid IN_PROGRESS → COMPLETED-övergången. Eftersom den är ren kan den enhetstestas med ett enkelt värdefixture utan att montera någon komponent.Hur strukturerar man ett React-projekt med domänbaserad modulorganisation?
Gruppera filer efter domänskiva snarare än efter teknisk typ. Till exempel:
src/domain/orders/ (typer, tillståndsmaskin, affärsregler), src/domain/clients/ (typer, frågor), src/domain/auth/ (rollkontext, guards), src/shared/ (UI-primitiver, hooks, utils). Varje domänmodul exporterar ett publikt API och döljer interna detaljer. Detta håller relaterad kod samlad, gör borttagningar säkra och skalas väl när nya domäner läggs till.Hur enhetstestar man affärsregler (tillståndsövergångar, kostnadsberäkningar) i ett React-projekt utan backend?
Extrahera all affärslogik till rena funktioner eller klasser i domänlagret utan React-beroenden. Tester importerar dessa funktioner direkt och kontrollerar returnerade värden eller felkoder. Till exempel:
expect(transition(order, 'AUTHORIZED')).toEqual({ ...order, status: 'AUTHORIZED' }). Vitest eller Jest är typiska val. Denna separation innebär att tester körs omedelbart utan jsdom, React Testing Library eller någon komponentmontering.Hur beräknar och formaterar man det auktoriserade beloppet inklusive moms i ett JavaScript-frontend?
Beräkna
authorizedAmount = Math.round(subtotalEstimated * 1.16 * 100) / 100 för att undvika flytpunktsdrift och producera ett värde med 2 decimaler. För visning, använd Intl.NumberFormat med lämplig locale och valutainställning snarare än manuell strängsammansättning. Håll det råa numeriska värdet i tillståndet och formatera bara vid renderingstillfället så att jämförelser och beräkningar alltid arbetar på tal.Vilka strategier kan man använda för att hantera globalt tillstånd i en medelstora React SPA utan att introducera Redux?
React Context tillsammans med
useReducer är det vanligaste lättviktsalternativet: en kontext håller tillståndet (ordrar, kunder, autentiseringsroll) och en dispatch-funktion exponerar typade åtgärder. För bättre prestanda separeras kontexter efter ansvar (AuthContext, OrderContext) för att undvika omrenderingar av orelaterade komponenter. Anpassade hooks (useOrders, useAuth) abstraherar kontextkonsumtionen. Om komplexiteten ökar är Zustand ett minimalt alternativ som undviker boilerplate.Hur designar man en domänmodell för en frontend SPA så att varje entitet refererar till andra med ID snarare än att bädda in hela objekt?
Lagra varje entitetstyp i sin egen normaliserade samling (t.ex.
customers: Record<string,Customer>, orders: Record<string,RepairOrder>). Entiteter refererar till varandra via ID:n (customerId, vehicleId). UI-komponenter får hela objektgrafen bara när det behövs, sammansatt i en selektor eller hook. Detta speglar vad ett backend-API skulle returnera, undviker duplicerad data och gör uppdateringar av enskilda entiteter O(1) utan kaskadkopior.Hur säkerställer man att affärsregler inte kan kringgås genom att manipulera UI:t direkt (t.ex. klicka på en dold knapp)?
Affärsregler måste finnas i domänlagret, inte bara i UI-villkor som döljer knappar. Varje tillståndsmuterande åtgärd går genom en domänfunktion som omvaliderar förutsättningar innan ett nytt tillstånd produceras. Att inaktivera eller dölja en knapp i UI:t är en bekvämlighet; den auktoritativa vakten är alltid i domänfunktionen. För en frontend-only-app kan localStorage manipuleras, så vid laddning bör data som kommer ut ur storage valideras och saneras innan den används.
Vilka React hook-mönster är mest användbara för att kapsla in orderlivscykellogik?
useReducer är idealiskt för komplexa tillstånd med många övergångar — varje åtgärdstyp mappas till ett domänfunktionsanrop. Reducern och dispatch omsluts i en anpassad hook useOrders som också synkroniserar med localStorage vid varje dispatch. useMemo kan härleda beräknade värden (t.ex. filtrerad orderlista, 110%-gräns) från råtillståndet utan att köras om vid varje rendering. useCallback stabiliserar händelsehanterare som skickas till barnkomponenter för att förhindra onödiga omrenderingar.Vad är Cross-Site Scripting (XSS) och hur förhindrar man det?
XSS är en sårbarhet där en angripare injicerar skadliga klientskript i en sida som ses av andra användare, vilket möjliggör cookiestöld, sessionskapning eller DOM-manipulation. Grundregeln är att aldrig lita på användarinmatning. Viktiga skyddsåtgärder: escapa/koda all utdata innan rendering, tillämpa en Content-Security-Policy-header, undvik innerHTML till förmån för textContent och använd ramverk som escapar automatiskt (React gör detta som standard).
Vad är Clickjacking och hur försvarar man sig mot det?
Clickjacking (UI Redress Attack) lurar en användare att klicka på ett element dolt under ett genomskinligt lager. Angriparen bäddar in din sida i en iframe och lägger sin UI ovanpå. De primära försvaren är X-Frame-Options HTTP-headern (satt till DENY eller SAMEORIGIN) eller Content-Security-Policy:s frame-ancestors-direktiv, som förhindrar att sidan bäddas in i iframes på andra ursprung.
Är det säkert att lagra autentiseringstoken i localStorage eller sessionStorage, och var ska de lagras?
Nej. Båda lagringsplatserna är läsbara av all JavaScript på sidan, vilket gör token sårbara för XSS. Den rekommenderade metoden är HttpOnly-cookies: webbläsaren skickar dem automatiskt med same-origin-förfrågningar men JavaScript kan inte läsa dem, vilket eliminerar XSS-vektorn. Som avvägning måste även CSRF-skydd (SameSite=Strict eller en CSRF-token) implementeras.
Vad är React Fiber och varför introducerades det?
React Fiber är en komplett omskrivning av Reacts reconciliation-algoritm, lanserad i React 16. Före Fiber var reconciliation synkron och rekursiv och kunde inte avbrytas, vilket orsakade hackiga UI för stora träd. Fiber representerar varje arbetsenhet som en länkad listnod, vilket låter React dela upp renderingen i bitar, pausa, prioritera och återuppta arbete. Detta möjliggjorde Concurrent Mode-funktioner som Suspense, error boundaries och hooks.
Hur fungerar React Reconciliation?
När tillståndet ändras bygger React ett nytt virtuellt DOM-träd och jämför det med det tidigare med en heuristisk O(n)-algoritm. Den jämför elementtyper först – om typen ändras förstör och återuppbygger React hela underträdet. Om typen är densamma uppdateras bara ändrade attribut. För listor används key-propen för att matcha gamla och nya objekt, vilket möjliggör återanvändning av oförändrade element utan ommontering.
Varför är key-propen viktig i React-listor och varför är det dålig praxis att använda arrayindex som key?
key-propen låter Reacts reconciler identifiera vilka element som har ändrats, lagts till eller tagits bort utan att montera om oförändrade element. Att använda arrayindex som key är problematiskt när listan sorteras om, filtreras eller element infogas/tas bort: React återanvänder fel komponentinstanser, vilket orsakar felaktigt tillstånd och onödiga omrenderingar. En stabil, unik identifierare (t.ex. ett databas-ID) bör användas istället.
Vad är en Higher-Order Component (HOC) i React?
En HOC är en funktion som tar en komponent och returnerar en ny komponent med injecterade props eller beteenden – en tillämpning av dekoratörsmönstret. HOC:ar möjliggör återanvändning av övergripande logik som autentiseringsgrindar eller analysspårning utan att modifiera den omslutna komponenten. De har till stor del ersatts av custom hooks, som är enklare och undviker problem som prop-kollisioner och svårgranskade komponentträd.
Vad är React Portals och när bör de användas?
Portals renderar en barnkomponent i en DOM-nod utanför föräldrakomponentens DOM-hierarki, men håller barnet kvar i Reacts komponentträd – kontext och händelsebubbling fungerar normalt. Använd dem för UI-element som visuellt måste undkomma overflow:hidden eller z-index-staplingskontextar: modaldialog, tooltips, popovers och notifikationer som behöver renderas på document body-nivå.
Vilket problem löser useTransition (eller startTransition) i React Concurrent Mode?
De löser det blockerande renderingsproblemet genom att markera tillståndsuppdateringar som icke-brådskande. React kan avbryta en sådan uppdatering om mer brådskande arbete – som en tangenttryckning – anländer, vilket håller UI:t responsivt under kostsamma omrenderingar. useTransition exponerar dessutom ett isPending-booleskt värde för att visa en laddningsindikator medan övergången pågår.
Om en händelsehanterare anropar setState tre gånger, hur många renderingar utlöser React?
I React 18 bara en, eftersom automatisk batching grupperar alla tillståndsuppdateringar inom alla asynkrona kontexter (setTimeout, Promises, native event handlers) i en enda omrendering. Före React 18 var batching begränsad till Reacts syntetiska händelsehanterare, så tre setState-anrop utanför det sammanhanget kunde utlösa upp till tre separata renderingar.