Functional Component — egy módja a React-komponensek létrehozásának hétköznapi JavaScript-függvények segítségével, ami a React 16.8 megjelenése és a hookok megjelenése után szabvánnyá vált. A funkcionális komponensek props-okat fogadnak és React-elemeket adnak vissza, nem igényelnek öröklődést a React.Component-től. A React, 2024 adatai szerint az új komponensek 97%-a függvényként íródik a React ökoszisztémában.
Főbb pontok
Functional Component (funkcionális komponens) — egy React-komponens, ami függvényként van definiálva, fogad egy props objektumot és visszaad egy React-elemet. A React 16.8 előtt az ilyen komponenseket stateless (állapot nélküli) néven illették, mert nem tudták kezelni a belső állapotot.
A hookok megjelenésével a React 16.8-ban (2019. február) a funkcionális komponensek hozzáférést kaptak az állapothoz (useState), mellékhatásokhoz (useEffect), kontextushoz (useContext) és referenciákhoz (useRef). A „stateless" kifejezés elavult — a modern funkcionális komponensek teljes mértékben kezelik az állapotot.
A React hivatalosan a funkcionális komponenseket ajánlja elsődleges módként a komponensek létrehozására. A react.dev webhelyen található összes dokumentáció, példa, oktatóanyag és új API (Server Components, Actions) a funkcionális megközelítésre épül. Az osztály alapú komponenseket nem távolították el, de a React új képességei csak hookokon keresztül érhetők el.
A legegyszerűbb funkcionális komponens — egy függvény, ami JSX-et ad vissza. Props-ot argumentumként fogad, nem igényel konstruktort, super hívást vagy this kötést. A props közvetlenül elérhető a függvény argumentumán keresztül — nincs 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>
);
Állapot hozzáadásához használja a useState-et. A hook egy két értékből álló tuple-t ad vissza: az aktuális állapotot és egy setter függvényt. Az osztályok this.setState-jával ellentétben a useState teljesen lecseréli az értéket, nem fésüli össze az előzővel.
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>
);
}
A hookok a modern React alapját képezik. Minden hook egy adott feladatot old meg: useState — állapot, useEffect — mellékhatások, useContext — hozzáférés a kontextushoz, useRef — referenciák DOM-elemekhez, useCallback és useMemo — memóizáció.
A useEffect egyszerre helyettesíti a componentDidMount, componentDidUpdate és componentWillUnmount metódusokat. Az első argumentum — egy callback a hatással, a második — a függőségek tömbje. Ha a tömb üres, a hatás egyszer fut le a csatlakoztatás után. Ha függőségek meg vannak adva — mindegyik megváltozásakor.
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>;
}
A funkcionális komponensek fő előnye — a logika újrafelhasználása egyedi hookokon keresztül. Ha egy osztály alapú komponensben a logika megduplázódott a componentDidMount és a componentDidUpdate között, addig a funkcionálisban egy külön függvénybe kerül ki extractionra, use előtaggal. Az egyedi hookok a HOC és a render props fő alternatívái.
A React kompozíciót ajánl az öröklődés helyett a kód komponensek közötti újrafelhasználására. A funkcionális komponensek ideálisak a kompozícióhoz: egy komponens több másikat is tartalmazhat, props-okat és children-t adva át nekik.
A children minta — amikor a komponens gyermekelemeket fogad a children prop-on keresztül — természetesen implementálódik: function Layout({ children }). A Vue slots analógja névvel ellátott props-komponenseken keresztül valósul meg: function Page({ header, sidebar, content }).
Az öröklődés a React-ben gyakorlatilag nem használt. Még az osztály alapú komponensek is, amelyek technikailag támogatják az extends-t, ritkán alkotnak egynél mélyebb hierarchiákat. A funkcionális komponensek kompozícióval teljes mértékben lefedik a kód újrafelhasználásának igényeit öröklődés nélkül.
A funkcionális komponensek beépített optimalizációs mechanizmusokkal rendelkeznek. React.memo — a PureComponent megfelelője függvényekhez: megakadályozza az újrarenderelést, ha a props nem változott (felületes összehasonlítás). useMemo gyorsítótárazza a számítások eredményét a renderelések között.
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 memóizálja a callback függvényeket, hogy ne jöjjenek létre újra minden rendereléskor. Ez kritikus, amikor függvényeket adunk át React.memo-ba csomagolt gyermekkomponenseknek: useCallback nélkül a gyermekkomponens minden alkalommal újrarenderelődik, mert a függvényre mutató referencia megváltozik.
A megközelítések közötti különbség túlmutat a szintaxison. Funkcionális komponensek — ez egy closure: az állapot és a hatások egy adott rendereléshez kötődnek. Osztály alapú komponensek — ez a this: az állapot mindig a this.state-ből származik, ami elavult lehet az aszinkron callback végrehajtásának pillanatában.
| Szempont | Funkcionális | Osztály alapú |
|---|---|---|
| Állapot | useState (elkülönített) | this.state + this.setState |
| Hatások | useEffect függőségekkel | componentDidMount + componentDidUpdate |
| Kontextus | useContext | Context.Consumer vagy static contextType |
| Optimalizálás | React.memo + useMemo | PureComponent + shouldComponentUpdate |
| Logika újrafelhasználása | Egyedi hookok | HOC / Render props |
| this | Nincs | bind a konstruktorban |
A funkcionális komponensek lineáris végrehajtási folyamatot biztosítanak. Egy osztály alapú komponensben a kapcsolódó logika gyakran több életciklus-metódus között van szétszórva. Például a WebSocket-feliratkozás a componentDidMount-ban van beállítva és a componentWillUnmount-ban eltávolítva. Egy funkcionális komponensben mindkét művelet — egy useEffect-ben egy tisztító függvénnyel.
A TypeScript természetesebben működik a funkcionális komponensekkel, mint az osztályokkal. A props típusosítása — egy interfész a függvény argumentumához. A visszaadott érték típusa — JSX.Element vagy ReactNode. A useState automatikusan kikövetkezteti a típust a kezdeti értékből.
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>
);
A modern TypeScript lehetővé teszi a useReducer típusosítását diszkriminált unió típusokkal, a Generics használatát egyedi hookokban és a children szigorú ellenőrzését a React.PropsWithChildren-en keresztül. A funkcionális komponensek TypeScript-tel teljes típusbiztonságot nyújtanak további absztrakciók nélkül.
Gyakran Ismételt Kérdések
A funkcionális komponensek egyszerűbbek: nincs konstruktor, bind, this és szétszórt életciklus-metódusok. A hookok lehetővé teszik a kapcsolódó logika csoportosítását. A React a hookok fejlesztésébe fektet be, nem az osztályokéba. A Server Components és az új funkciók csak függvényekben érhetők el.
Igen, a useEffect-en keresztül egy timer-rel belül és egy tisztító függvénnyel a clearInterval számára. Figyeljen a closure-re: ha egy számlálót ketyeget, használja a setState funkcionális formáját: setCount(c => c + 1), hogy ne függjön a régi értéktől a closure-ben.
Használja a useRef-et az előző érték tárolására. Frissítse a ref-et a useEffect-ben minden renderelés után. A vizuális összehasonlításhoz a usePrevious egyedi hook segít: const prev = usePrevious(value);
React.memo — egy HOC a teljes komponens memóizálásához: megakadályozza az újrarenderelést, ha a props nem változott. useMemo — egy hook egy adott érték memóizálásához a komponensen belül: gyorsítótárazza a függvény eredményét a renderelések között egy függőségi tömb alapján.
A legegyszerűbb mód — useState inicializálással props-ból + useEffect props függőséggel a szinkronizációhoz. Ritka esetekben a React azt ajánlja: használjon kulcsot (key) a komponens kényszerített újraépítéséhez a bemeneti adatok megváltozásakor.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is