Functional Component — är ett sätt att skapa React-komponenter med vanliga JavaScript-funktioner, som blev standard efter lanseringen av React 16.8 och tillkomsten av hooks. Funktionella komponenter tar emot props och returnerar React-element, utan att kräva arv från React.Component. Enligt data från React, 2024 skrivs 97% av nya komponenter i React-ekosystemet som funktioner.
Huvudpunkter
Functional Component (funktionell komponent) — är en React-komponent definierad som en funktion, som tar emot ett props-objekt och returnerar ett React-element. Före React 16.8 kallades sådana komponenter stateless (utan tillstånd), eftersom de inte kunde hantera internt tillstånd.
Med tillkomsten av hooks i React 16.8 (februari 2019) fick funktionella komponenter tillgång till tillstånd (useState), sidoeffekter (useEffect), kontext (useContext) och referenser (useRef). Termen ”stateless” är föråldrad — moderna funktionella komponenter hanterar tillstånd fullt ut.
React rekommenderar officiellt funktionella komponenter som det huvudsakliga sättet att skapa komponenter. All dokumentation på react.dev, exempel, handledningar och nya API:er (Server Components, Actions) är byggda på det funktionella angreppssättet. Klasskomponenter har inte tagits bort, men nya React-funktioner är endast tillgängliga via hooks.
Den enklaste funktionella komponenten — en funktion som returnerar JSX. Den tar emot props som argument, kräver ingen konstruktor, super-anrop eller this-bindning. Props är tillgängliga direkt via funktionens argument — inget this.props.
// Functional component without state
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Arrow function (common variant)
const Greeting = ({ name }) => (
<h1>Hello, {name}!</h1>
);
För att lägga till tillstånd, använd useState. Hooken returnerar en tupel med två värden: aktuellt tillstånd och en setter-funktion. Till skillnad från klassens this.setState ersätter useState värdet helt, utan att slå samman det med det föregående.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
Hooks är grunden för modern React. Varje hook löser en specifik uppgift: useState — tillstånd, useEffect — sidoeffekter, useContext — åtkomst till kontext, useRef — referenser till DOM-element, useCallback och useMemo — memoisering.
useEffect ersätter samtidigt componentDidMount, componentDidUpdate och componentWillUnmount. Det första argumentet — en callback med effekten, det andra — en beroendematris. Om matrisen är tom körs effekten en gång efter montering. Om beroenden anges — vid varje ändring av något av dem.
import React, { useState, useEffect } from 'react';
function UserData({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
let cancelled = false;
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
if (!cancelled) setUser(data);
});
// Cleanup - analog of componentWillUnmount
return () => { cancelled = true; };
}, [userId]); // Dependency
return <div>{user?.name}</div>;
}
Den främsta fördelen med funktionella komponenter — återanvändning av logik genom anpassade hooks. Om logiken i en klasskomponent duplicerades mellan componentDidMount och componentDidUpdate, extraheras den i en funktionell komponent till en separat funktion med prefixet use. Anpassade hooks är det främsta alternativet till HOC och render props.
React rekommenderar komposition, inte arv, för återanvändning av kod mellan komponenter. Funktionella komponenter är idealiska för komposition: en komponent kan innehålla flera andra och skicka props och children till dem.
Mönstret children — när en komponent tar emot underordnade element via prop children — implementeras naturligt: function Layout({ children }). Motsvarigheten till slots från Vue implementeras via namngivna props-komponenter: function Page({ header, sidebar, content }).
Arv används praktiskt taget inte i React. Även klasskomponenter, som tekniskt stöder extends, bildar sällan hierarkier djupare än en nivå. Funktionella komponenter med komposition täcker helt behoven av kodåteranvändning utan arv.
Funktionella komponenter har inbyggda optimeringsmekanismer. React.memo — motsvarigheten till PureComponent för funktioner: förhindrar omrendering om props inte har ändrats (ytlig jämförelse). useMemo cachelagrar resultatet av beräkningar mellan renderingar.
import React, { useMemo } from 'react';
// React.memo - memoize component
const ExpensiveList = React.memo(({ items }) => {
return <ul>
{items.map(item =>
<li key={item.id}>{item.name}</li>
)}
</ul>;
});
// useMemo - caching result
function Dashboard({ transactions }) {
const summary = useMemo(() => {
return transactions.reduce((acc, t) => acc + t.amount, 0);
}, [transactions]);
return <p>Total: {summary}</p>;
}
useCallback memoiserar callback-funktioner så att de inte skapas på nytt vid varje rendering. Detta är avgörande när man skickar funktioner till underordnade komponenter inslagna i React.memo: utan useCallback kommer den underordnade komponenten att rendera om varje gång, eftersom referensen till funktionen ändras.
Skillnaden mellan angreppssätten går utöver syntax. Funktionella komponenter — är en closure: tillstånd och effekter är bundna till en specifik rendering. Klasskomponenter — är this: tillstånd hämtas alltid från this.state, som kan vara föråldrat vid tidpunkten för exekvering av en asynkron callback.
| Aspekt | Funktionell | Klass |
|---|---|---|
| Tillstånd | useState (isolerat) | this.state + this.setState |
| Effekter | useEffect med beroenden | componentDidMount + componentDidUpdate |
| Kontext | useContext | Context.Consumer eller static contextType |
| Optimering | React.memo + useMemo | PureComponent + shouldComponentUpdate |
| Logikåteranvändning | Anpassade hooks | HOC / Render props |
| this | Nej | bind i konstruktor |
Funktionella komponenter ger linjärt exekveringsflöde. I en klasskomponent är relaterad logik ofta utspridd över flera livscykelmetoder. Till exempel ställs en WebSocket-prenumeration in i componentDidMount och tas bort i componentWillUnmount. I en funktionell komponent finns båda operationerna — i en useEffect med en rensningsfunktion.
TypeScript fungerar mer naturligt med funktionella komponenter än med klasser. Typning av props — ett gränssnitt för funktionens argument. Typen av returvärdet — JSX.Element eller ReactNode. useState härleder automatiskt typen från initialvärdet.
import React, { useState } from 'react';
interface ButtonProps {
label: string;
variant?: 'primary' | 'secondary';
onClick: () => void;
}
const Button: React.FC<ButtonProps> =
({ label, variant = 'primary', onClick }) => (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{label}
</button>
);
Modernt TypeScript tillåter typning av useReducer med diskriminerade unionstyper, Generics i anpassade hooks och strikt kontroll av children via React.PropsWithChildren. Funktionella komponenter med TypeScript ger fullständig typsäkerhet utan extra abstraktioner.
Vanliga frågor
Funktionella komponenter är enklare: ingen konstruktor, bind, this och spridda livscykelmetoder. Hooks möjliggör gruppering av relaterad logik. React investerar resurser i utvecklingen av hooks, inte klasser. Server Components och nya funktioner är endast tillgängliga i funktioner.
Ja, via useEffect med en timer inuti och en rensningsfunktion för clearInterval. Var uppmärksam på closure: om du tickar en räknare, använd den funktionella formen av setState: setCount(c => c + 1), för att inte vara beroende av det gamla värdet i closuren.
Använd useRef för att lagra det tidigare värdet. Uppdatera ref i useEffect efter varje rendering. För visuell jämförelse hjälper den anpassade hooken usePrevious: const prev = usePrevious(value);
React.memo — en HOC för memoisering av en hel komponent: förhindrar omrendering om props inte har ändrats. useMemo — en hook för memoisering av ett specifikt värde inuti komponenten: cachelagrar resultatet av en funktion mellan renderingar baserat på en beroendematris.
Det enklaste sättet — useState med initiering från props + useEffect med beroende på props för synkronisering. För sällsynta fall rekommenderar React: använd en nyckel (key) för att tvinga fram återskapande av komponenten när indata ändras.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också