import React, { useState } from 'react';
function Example() {
const [state, setState] = useState({});
// ...
}
if you write function components and realise that you need to add state
// first render
useState('Mary') // 1 Initialize
useEffect(persistForm) // 2
useState('Poppins') // 3
useEffect(updateTitle) // 4
// second render
useState('Mary') // 1 Read
useEffect(persistForm) // 2
useState('Poppins') // 3
useEffect(updateTitle) // 4
useState('Mary') // 1. Read the name state
// useEffect(persistForm) // 🔴 This Hook was skipped!
useState('Poppins') // 🔴 2 (but was 3).
useEffect(updateTitle) // 🔴 3 (but was 4).
if (name !== '') {
useEffect(function persistForm() {
//...
});
}
function Counter({initialCount}) {
const [count, setCount] = useState(()=>initialCount);
return (
<>
<button onClick={
() => setCount(initialCount)}> Reset</button>
<button onClick={
() => setCount(prevCount => prevCount + 1)}>Plus</button>
</>
);
}
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
// Clean up the subscription
subscription.unsubscribe();
};
});
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
const memoizedValue = useMemo(() =>
computeExpensiveValue(a, b),
[a, b]);
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>
Focus the input</button>
</>
);
}
function Box() {
const [state, setState] = useState({
left: 0, top: 0,
width: 100, height: 100 });
}
//spreading ensures we don't lose data
setState(state => ({ ...state, left: 10, top: 10 }));
// Recommended way
function Box() {
const [position, setPosition] = useState({
left: 0, top: 0 });
const [size, setSize] = useState({
width: 100, height: 100 });
}
useEffect(() => {
fetchData();
}, []);
useEffect(() => {
let ignore = false;
async function fetchProduct() {
const response = await fetch('http://myapi/product/1');
const json = await response.json();
if (!ignore) setProduct(json);
}
return () => { ignore = true };
}, []);
const Button = React.memo((props) => {
// your component
});
The useCallback Hook lets you keep the same callback reference between re-renders
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
2. useMemo Hook makes it easier to control when individual children update, reducing the need for pure components.
function Parent({ a, b }) {
const child1 = useMemo(() => <Child1 a={a} />, [a]);
const child2 = useMemo(() => <Child2 b={b} />, [b]);
return (
<>
{child1}
{child2}
</>
)
}
3. useReducer Hook reduces the need to pass callbacks deeply
const TodosDispatch = React.createContext(null);
function TodosApp() {
const [todos, dispatch] = useReducer(todosReducer);
return (
<TodosDispatch.Provider value={dispatch}>
<DeepTree todos={todos} />
</TodosDispatch.Provider>
);
}