Use state and other React features without writing a class
import React, { Fragment, useState } from 'react';
export class GreetingClass extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'Bilbo Baggins',
age: 25,
};
this.onHandleNameChange = this.onHandleNameChange.bind(this);
this.onHandleAgeChange = this.onHandleAgeChange.bind(this);
}
onHandleNameChange(e) {
this.setState({
name: e.target.value,
});
}
onHandleAgeChange(e) {
this.setState({
age: e.target.value,
});
}
render() {
const { name, age } = this.state;
return (
Name
Age
);
}
}
export function Greeting() {
const [name, setName] = useState('Albus Dumbledore');
const [age, setAge] = useState(175);
function handleNameChange(e) {
setName(e.target.value);
}
function handleAgeChange(e) {
setAge(e.target.value);
}
return (
Name
Age
);
}
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}
cDM & cDU
import { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
);
}
cWU
import { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
import React, { Fragment, useState, useEffect } from 'react';
export 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;
}
export function useDocumentTitle(title) {
useEffect(() => {
document.title = title;
});
}
export function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
function onHandleChange(e) {
setValue(e.target.value);
}
return { value, onChange: onHandleChange };
}
export function CustomHook() {
const title = useFormInput('Heading');
const designation = useFormInput('Software Engineer');
const width = useWindowWidth();
useDocumentTitle(title.value);
return (
Title
Designation
Width
);
}
function Example() {
const locale = useContext(LocaleContext);
const theme = useContext(ThemeContext);
// ...
}
Use hooks like redux
import React, { useReducer } from 'react';
const initialState = {
loading: false,
count: 0,
};
const reducer = (state, action) => {
switch (action.type) {
case 'increment': {
return { ...state, count: state.count + 1, loading: false };
}
case 'decrement': {
return { ...state, count: state.count - 1, loading: false };
}
case 'loading': {
return { ...state, loading: true };
}
default: {
return state;
}
}
};
const delay = (time = 1500) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(true);
}, time);
});
};
function PokemonInfo() {
const [{ count, loading }, dispatch] = useReducer(reducer, initialState);
const onHandleIncrement = async () => {
dispatch({ type: 'loading' });
await delay(500);
dispatch({ type: 'increment' });
};
const onHandleDecrement = async () => {
dispatch({ type: 'loading' });
await delay(500);
dispatch({ type: 'decrement' });
};
return (
Count {loading ? 'loading..' : count}
);
}
export default PokemonInfo;
By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates.
function FriendStatus(props) {
// ...
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
}
// Mount with { friend: { id: 100 } } props
ChatAPI.subscribeToFriendStatus(100, handleStatusChange); // Run first effect
// Update with { friend: { id: 200 } } props
ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // Clean up previous effect
ChatAPI.subscribeToFriendStatus(200, handleStatusChange); // Run next effect
// Update with { friend: { id: 300 } } props
ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // Clean up previous effect
ChatAPI.subscribeToFriendStatus(300, handleStatusChange); // Run next effect
// Unmount
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // Clean up last effect
// old way
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
document.title = `You clicked ${this.state.count} times`;
}
}
// hooks way
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return {count}
;
}
useEffect(() => {
document.title = 'Hello, ' + name;
}, []); // Wrong: name is missing in deps
function Counter() {
const [count, setCount] = useState(0);
function handleAlertClick() {
setTimeout(() => {
alert('You clicked on: ' + count);
}, 3000);
}
return (
You clicked {count} times
);
}