Hooks are a new addition to React 16.8. Hooks are a new API that allows us to have state, and other React features, in Functional Components.
- You can still use classes, but hooks are recommended.
- Complex components become hard to understand with Classes.
- Hooks let you split one component into smaller functions based on what pieces are related.
- You have to understand how this works in JavaScript.
- You have to remember to bind the event handlers.
Took @dan_abramov's code from #ReactConf2018 and visualised it so you could see the benefits that React Hooks bring us. pic.twitter.com/dKyOQsG0Gd
— Pavel (@prchdk) October 29, 2018
- Only call Hooks at the top level.
- Don’t call Hooks inside loops, conditions, or nested functions.
- Only call Hooks from React function components.
- You can create custom hooks.
This flowchart explains the lifecycle of a Hooks component.
The React useState Hook allows to track state in a function component. State generally refers to data or properties that need to be tracked through the application.
function Example() {
// We are going to use the "count" variable and the "setCount" function.
// useState hook will always return a pair of values:
// the current state and a function that updates it. We are using array destructuring.
// The only argument to useState is the initial state.
const [count, setCount] = React.useState(0);
return <p>{count}</p>
}You can use multiple useState Hooks in the same component. Let's take a look at the example below.
function Form() {
const [values, setValues] = React.useState({
name: '',
age: null
});
function handleOnChange(event) {
const { target: { value, name } } = event;
setValues({
...values,
[name]: value
});
}
function handleOnSubmit(event) {
event.preventDefault();
console.log('>>> Values', values);
}
const element = (
<form onSubmit={handleOnSubmit}>
<label htmlFor="name">Name</label>
<input id="name" name="name" type="string" onChange={handleOnChange}/>
<label htmlFor="age">Age</label>
<input id="age" name="age" type="number" onChange={handleOnChange}/>
<button type="submit">
Submit
</button>
</form>
);
return element;
}- We highly recommend visiting the Frequently asked questions
The useEffect Hook allows performing side effects in your components.
Common use cases:
- Fetch data.
- Directly update the DOM.
- Timers.
Effects without cleanup
useEffect(() => {
//Runs on every render
});
useEffect(() => {
//Runs only on the first render
}, []);
useEffect(() => {
//Runs on the first render
//And any time any dependency value changes
}, [prop, state]);Effects with cleanup
useEffect(() => {
//Runs on Unmounting
return () => {
//Timeouts, subscriptions, event listeners, and other effects that are no longer needed should be disposed.
}
});You can use multiple useEffect hooks in the same component. Let's take a look at the example below.
const POKEMON_ENDPOINT = 'https://pokeapi.co/api/v2/pokemon';
function PokemonCard(props) {
const { name, sprites } = props;
React.useEffect(() => {
console.log('>>> Pokemon updated');
});
return (
<div key={name}>
<img src={sprites.other.dream_world.front_default} alt={`${name} image`} width="200"/>
<p>{name}</p>
</div>
);
}
function App () {
const [pokemons, setPokemons] = React.useState([]);
React.useEffect(async () => {
await fetchPokemons();
console.log('>>> Pokemons fetched');
}, []);
async function fetchPokemonData({ url }) {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (error) {
setPokemons([]);
}
}
async function fetchPokemons() {
// Changing the state
try {
const response = await fetch(POKEMON_ENDPOINT);
const data = await response.json();
const pokemonsDetailed = [];
for (const pokemon of data.results) {
const pokemonData = await fetchPokemonData(pokemon);
pokemonsDetailed.push(pokemonData);
}
setPokemons(pokemonsDetailed);
} catch (error) {
setPokemons([]);
}
};
const element = pokemons.length === 0 ? <p> Loading... </p> : pokemons.map(pokemon => <PokemonCard key={pokemon.id} {...pokemon}/>)
return (
<div>
{element}
</div>
);
}The useRef hook allows creating a reference to the DOM element. It can be used to access a DOM element directly.
// It returns an Object called current.
const refContainer = useRef(initialValue); function App() {
const [inputValue, setInputValue] = React.useState('');
const name = React.useRef(null);
return (
<>
<h1>Input value: {name.current?.value || ''}</h1>
<label htmlFor='name'>Name</label>
<input
id='name'
type='text'
value={inputValue}
ref={name}
onChange={(e) => {
// printing the object props
console.dir(name.current);
setInputValue(e.target.value)
}}
/>
</>
);
}In general, we want to let React handle all DOM manipulation, instead of querying the DOM.
function App() {
const inputElement = React.useRef();
const focusInput = () => {
inputElement.current.value = "Now I'm being focused.";
inputElement.current.focus();
};
return (
<>
<input type="text" ref={inputElement} />
<button onClick={focusInput}>Focus Input</button>
</>
);
}The
useRefHook can also be used to keep track of previous state values.
- In your forked
react-tutorialrepo, create a new branch named feature/basic-hooks. - Create an
index.htmlfile within the8-component-lifecyclefolder. - You should create the following App and Child Components using the React hooks described in this section.
- Push your changes and create the Pull Request.

