React Hooks: Notes Taken
3 min readOct 26, 2018
References
Installation
yarn add react@next react-dom@nextBasic example
const FriendStatus = ({ id }) => {
const [isOnline, setIsOnline] = useState(null); const handleStatusChange = (status) => {
setIsOnline(status.isOnline);
} useEffect(() => {
ChatAPI.subscribeToFriendStatus(id, handleStatusChange); return () => {
ChatAPI.unsubscribeFromFriendStatus(id, handleStatusChange);
};
}); if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
Basic rules
- Only call Hooks at the top level.
- Only call Hooks from React function components.
See aforementioned ESLint plugin.
So…
- They can’t be used within class components
- They can’t be used in combination with
for,if, ... as they relies on an order in which they are called.
useState
Example
const Balloon = ({ initialSize, powerOfBlow }) => {
const [size, setSize] = useState(initialSize);
const onBlow = () => setSize(size + powerOfBlow) return <div onClick={onBlow}>Size of the balloon: {size}</div>;
}
Syntax:
@param {any} Initial state value
@returns Pair
- fst {any} Value of state
- snd {function} callback to set new value of state- Type of the state can be anything unlike state within
classcomponents (in that case object must be used). - It is encouraged to use multiple
useStatewithin afunctioncomponent, instead of using one single state object as is inclasscomponents. - Possible minification
useEffect
Example:
useEffect(() => {
document.title = `You clicked ${count} times`; return () => {
document.title = 'You have never clicked!';
}
});
Syntax:
@param {Function} effect Function that is called when component performs DOM changes.
@param {Array} shouldApply Array of values that should be checked for changes before applying an effect. If values between renders do not change, the effect is not applied again.@returns {Function} Cleanup function that is called before a component is unmounted and before new render.
Notes:
- For side effects :) DOM, logs, fetching APIs…
- It is called after every render — even the first one.
- Unlike class lifecycle methods the
useEffectdo not block the browser. - For blocking effects there is
useLayoutEffect.
shouldUpdate?
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.id, handleStatusChange); return () => {
ChatAPI.unsubscribeFromFriendStatus(props.id, handleStatusChange);
};
}, [props.id]);
- For checking the
shouldApplyparameter the shallow compare is used. - Use
[]if you need to use effect just for bothdidMountandwillUnmountphases. It is discouraged.
Custom hooks
const useFriendStatus = (id) => {
const [isOnline, setIsOnline] = useState(null); const handleStatusChange = (status) => {
setIsOnline(status.isOnline);
} useEffect(() => {
ChatAPI.subscribeToFriendStatus(id, handleStatusChange); return () => {
ChatAPI.unsubscribeFromFriendStatus(id, handleStatusChange);
};
}); return isOnline;
}const FriendStatus = ({ id }) => {
const isOnline = useFriendStatus(id); if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
- The name of a function starts with
use, e.g.useRedux. - Two components that use the same hooks does not share the same state.
- Use cases: form handling, animation, declarative subscriptions, timers, …
Other Hooks
useCallback
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);- Bye, bye withHandlers 😝
useReducer
const reducer = (state, action) => {
switch (action.type) {
case 'reset':
return {count: action.payload};
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
}
}const [state, dispatch] = useReducer(
reducer,
initialState,
{ type: 'reset', payload: initialCount },
);
useRef && useImperativeMethods
- Another way to use refs…
React-redux
- Use
React.useReducerfor local state - Use
ReactRedux.useReduxfor global state
import * as actions from './actions'const Counter = () => {
const [count, {increment, decrement}] = useRedux(state => state.count, actions);
return (
<Fragment>
Count: {count}
<button onClick={() => increment()}>+</button>
<button onClick={() => decrement()}>-</button>
</Fragment>
);
}
