Understanding React Hooks
Posted on:
sourceAfter spending a few weeks working with and learning React Hooks, I wanted to collate it all into a quick cheatsheet for myself, I hope you can find some value in it.
Insights
- Can refactor all class components to function components
- Ended up with lower filesizes of >15%
- Simpler lifecycle methods
- Everything is so much nicer now
Hooks
useState
- replaces all state functions
- type should easily be inferred based on initial value but still worth setting
const [age, setAge] = useState < number > 28
return (
<Fragment>
<p>I am {age} Years of Age</p>
<button onClick={() => setAge(age + 1)}>Get older! </button>
</Fragment>
)
useEffect
- combines
componentDidMount
andcomponentWillUnmount
andcomponetnDidUpdate
- no types needed
useEffect(() => {
// do something on mount
return () => {
// do something on unmount (cleanup)
}
}, []) //listen for change to x in [array] then trigger (update), empty for only mount / unmount
useRef
- usually used for referencing dom nodes
null
can be used as the initial value and a generic html can be used for the ref type
- Replaces
createRef
- Can also be used as a replacement for instance properties on classes
- Type should be inferred
const MyInput = () => {
const inputRef = useRef < HTMLInputElement > null
return <input ref={inputRef} />
}
useMemo / useCallback
- shorthand for memoising functions
_ types inferred
_ make sure to specify the types of the parameters of the callback for useCallback, otherwise they will be set to
any
const value = 10
// inferred as number
const result = useMemo(() => value * 2, [value])
const multiplier = 2
// inferred as (value: number) => number
const multiply = useCallback((value: number) => value * multiplier, [multiplier])
useReducer
- Exactly like a redux router
- Typed in the same way
interface State {
value: number;
}
type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'incrementAmount', amount: number }
const counterReducer = (state: State, action: Action) => {
switch (action.type) {
case 'increment':
return { value: state.value + 1 }
case 'decrement':
return { value: state.value - 1 }
case 'incrementAmount':
return { value: state.value + action.amount }
default:
throw new Error()
}
}
const [state, dispatch] = useReducer(counterReducer, { value: 0 })
dispatch({ type: 'increment' })
dispatch({ type: 'decrement' })
dispatch({ type: 'incrementAmount', amount: 10 })
// TypeScript compilation error
dispatch({ type: 'invalidActionType' })
useContext
- infer its types based on the context object that is passed in
const ThemeContext = React.createContext('light')
const Display = () => {
const theme = useContext(ThemeContext)
return (
<div
style={{
background: theme === 'dark' ? 'black' : 'papayawhip',
color: theme === 'dark' ? 'white' : 'palevioletred',
width: '100%',
minHeight: '200px',
}}
>
{'The theme here is ' + theme}
</div>
)
}
useDebugValue
- used for displaying values in React Developer Tools
- type is inferred
const date = new Date()
useDebugValue(date, date => date.toISOString())