Espen Henriksen
Front-end team lead
Oslo Market Solutions
espen_dev
esphen
React Hooks
An introduction
What the hook?
Hooks
- New API
- Introduced in React 16.8
- "Hook into" React features
- Use state and other features without writing a class
- Not breaking, classes still around
- The future of components
Why now?
- Classes only way to use state
- Classes are verbose, explicit and imperative
- Other patterns have emerged
- HoCs are hard
- Render prop components incur "wrapper hell"
- Consolidate these stateful patterns into a first-class citizen
What's wrong with classes?
Challenges today
- Boilerplate
- Reusing stateful logic between components
- Related logic is fragmented
- Classes are hard for people
- Classes are hard for machines
Rethinking React
- Use react features by calling a function
- Side effects consistent by default
- Colocate stateful logic into functions
- Extract functions of related stateful logic
- Re-use extracted stateful functions
Hooks!
- Solve most of the issues with classes
- 100% backwards-compatible
- Almost all usecases for classes are covered
- No new concepts like generators or HoCs
- No plans to remove classes from React
Let's use hooks!
Live coding
In summary
Ergronomic API
Custom hooks
Data fetching is coming
Constraints
- Rely on call order
- Only call hooks at the top level
- No conditional hooks
- No hooks in loops
- Only in functional components
No conditional hooks
// 🔴 We're breaking the first rule by using a Hook in a condition
if (name !== '') {
useEffect(function persistForm() {
localStorage.setItem('formData', name);
});
}
useEffect(function persistForm() {
// 👍 We're not breaking the first rule anymore
if (name !== '') {
localStorage.setItem('formData', name);
}
});
ESLint plugin
Types of hooks
useState
const [state, setState] = useState(initialState);
useEffect
useEffect(didUpdate, shouldUpdateFor);
// Example
useEffect(() => {
setInterval(doSomething, interval);
return () => {
clearInterval(doSomething);
};
}, [interval])
useContext
const contextValue = useContext(Context);
useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);
// Example
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}
Memoization
// Returns a memoized callback
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
// Returns a memoized value
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useRef
const refContainer = useRef(initialValue);
useDebugValue
useDebugValue(value);
// Example
// Show a label in DevTools next to this Hook
// e.g. "FriendStatus: Online"
useDebugValue(isOnline ? 'Online' : 'Offline');
What next?
Watch the talk
Read the docs
Start using it!
Fin
Questions?
https://slides.com/esphen/hooks
React hooks
By Eline H
React hooks
An introduction to React hooks
- 23