Úvod do React Hooks

Miroslav Uhlíř
4 min readNov 23, 2018

--

Cílem React Hooks je zjednodušit tvorbu React aplikací. Umožňují použít state a lifecycle metody ve funkcionálních komponentách. Nahrazují HOC (higher order components) a téměř ve většině případech také render props. React komponenty nejsou nejvhodnější na sdílení kódu, protože jejich hlavním úkolem je vykreslovat UI (uživatelská rozhraní). React Hooks dovolují lepší sdílení kódu napříč aplikací.

Hook useState

Doteď bylo možné použít state pouze v class komponentách.

Ukázka class komponenty

class CounterClass extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.handleCounter = this.handleCounter.bind(this);
}
handleCounter(value) {
this.setState({
count: value
});

}
render() {
return (
<div>
<div>
<h2>class component</h2>
<p>{this.state.count}</p>
<button onClick={() => this.handleCounter(this.state.count + 1)}>
Increment
</button>
<button onClick={()=>this.handleCounter(this.state.count — 1)}>
Decrement
</button>
</div>
</div>

);

}

}

Předchozí class komponenta vytvořená jako funkcionální komponenta s použitím useState

function CounterFunction() {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count — 1);
return (
<div>
<h2>function with useState hook</h2>
<p>{count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);

}
Class komponenta a Reach Hook useState

useState je funkce, která umožňuje použít state ve funkcionální komponentě. V návratové hodnotě vrací pole.

const [count, setCount] = useState(0);

Pro získání položek z pole používáme destruction array. Položky z pole si můžeme libovolně pojmenovat.

Ukázka, jak funguje array destruction

const items = [‘firstItem’, ‘secondItem’];
const [myFirstItem, mySecondItem] = items;

Ekvivalentem pro destruction array je

myFirstItem = items[0];
mySecondItem = items[1];

useState vrací proměnnou count a funkci setCount. K hodnotě přistupujeme přímo pomocí count. setCount nastaví hodnotu count, funguje podobně jako setState v class komponentě.

V class komponentě jsme měli všechny states v jednom objektu. useState můžeme mít v komponentě vícekrát.

const [position, setPosition] = useState(0);
const [isOn, setIsOn] = useState(false);

Při použití useState nepotřebujeme constructor, bind a this. Výsledný kód je mnohem kratší a přehlednější.

Hook useEffect

useEffect je kombinace componentDidMount, componentDidUpdate a componentWillUnmount. Tyto metody slouží k provádění side effects - volání API, ruční změna DOM nebo použití event listeners. Odtud slovo effect v názvu useEffect.

Ukázka useEffect ve funkcionální komponentě

function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch(“https://api.github.com/users")
.then(response => response.json())
.then(data => {
setUsers(data);
});
}, []);
return (
<div>
{users.map(user => (
<div key={user.id}>
<p>{user.login}</p>
</div>
))}
</div>

);

}
Volání fetch API v useEffect

Všimněte si druhého paratmertu v podobě prázdného pole ve funkci useEffect. Tímto určujeme, aby se useEffect zavolalo pouze jednou. Nahrazuje componentDidMount. Pokud by zde nebyl parametr v podobě prázdného pole, useEffect by se volalo po každém render a fungovalo by jako componentDidUpdate.

useEffect můžeme zavolat jen při změně určité proměnné. Pokud do pole vložíme parametr, tak se useEffect zavolá jen při změně hodnoty tohoto parametru.

useEffect(
() => {
},
[count]

);

Pokud se změnilo count, zavolá se useEffect. Porovná hodnotu v předchozím a následujícím vykreslení. Jestliže je hodnota stejná, useEffect se nezavolá.

return v useEffect funguje jako componentWillUnmout

function WindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {

const handleResize = () => setWidth(window.innerWidth);

window.addEventListener(“resize”, handleResize);
return () => {
window.removeEventListener(“resize”, handleResize);

};

});
return <span>Window width {width}</span>;

}

Při odstranění komponenty z DOM je také potřeba odstranit subscription, aby došlo k uvolnění nepoužívané paměti. Výhodou useEffect je, že side effect je zapouzdřen v jedné funkci. V případě class komponenty by bylo subscription v metodě componentDidMount a cleanup fáze v metodě componentWillUnmount.

Custom Hook

Hooks jsou JavaScriptové funkce. Můžeme je spojit v jiné JavaScriptové funkci a vytvořit si vlastní React Hooks a pak tuto funkci sdílet napříč různými komponentami.

V posledním příkladu jsme vytvořili funkci, která získává šířku okna. Tuto logiku bychom rádi použili ve více komponentách. Vytvoříme custom Hook, který pojmenujeme useWindowWidth. Vyextrahujeme logiku a vytvoříme tak znovupoužitelnou funkci.

function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener(“resize”, handleResize);
return () => {
window.removeEventListener(“resize”, handleResize);
};
});
return width;

}
function MyComponent() {
const width = useWindowWidth();
return <span>window width {width}</span>;

}

useWindowWidth použijeme v nově vytvořené komponentě MyComponent. Custom Hook by měl začínat slovem use. Hook pak může být zkontrolován například pomocí ESLint, jestli dodržuje předepsaná pravidla. Custom Hook řeší nevýhodu HOC, kde se může stát hierarchie nepřehlednou kvůli vnořování komponent do sebe.

Hooks pravidla

React Hooks musíme vždy volat z React komponenty. Nesmíme je volat v cyklech nebo podmínkách. Musíme je vždy volat ve stejném pořadí. Podmínku můžeme umístit až do samotného těla Hook. Pokud bychom nevolali React Hooks ve stejném pořadí, mohlo by například dojít k tomu, že bychom změnili jiný state.

Závěrem

Představili jsme si pouze základní Reack Hooks. Existuje jich více - useReducer, useRef, useContext a další. Ve funkcionální komponentě můžeme díky React Hooks použít state a lifecycle metody. Výsledný kód je také kratší a přehlednější. Custom Hook umožňuje lepší sdílení kódu. Nemusíme používat HOC. React Hooks nabízí řadu výhod. Můžeme proto předpokládat, že funkcionální komponenty budou v budoucnu hlavní způsob vytváření komponent v Reactu.

--

--