useState
, useEffect
, useRef
and React.memo
are the hooks and the higher order component that allow you to replace React class component lifecycle methods.
useState
Use: to manage a component’s local state.
Purpose: to replace the need for this.state and constructor.
useEffect
Use: to manage side effects (Ex. an API request, tracking analytics, interacting with DOM not contained inside your React app, etc).
Purpose: to replace the need for lifecycle methods (React Component Lifecycle Methods Cheatsheet).
useRef
Use: to provide the way to access DOM nodes or HTML elements created in the render method.
Purpose: to helps the useEffect
to replaces the need for componentDidUpdate
.
memo
Use: to manage a component’s re-rendering.
Purpose: to replace the need for shouldComponentUpdate
.
Explanation with Words and Code
const {useEffect, useState, useRef, memo} = React; const ReactLifecycleHooks = (props) => { // Commonly Used Hooks // Purpose: Initialize state, read and update state variable. // The useState hook allows you to read and update a state variable. // The usetState function returns an array containing the current value and the function to // update the value. const [desc, setDesc] = useState('user'); const [prevCount, setPrevCount] = useState(null); // The mounted variable of useRef here is used to check the component is rendered. const mounted = useRef(); console.log('render'); // The useEffect hook takes 2 arguments, a function containing a side effect action and an array. // The array contains the variable(s) that you want to track. // When a value in the array changes, the side effect function is executed. // The empty array is passed to useEffect as its second argument // in the purpose of replacing the useEffect with componentDidMount & componentWillUnmount. useEffect(() => { console.log('componentDidMount'); // Lifecycle: Mount immediately after render. // Purpose: Initialize state that requires DOM nodes, Network requests and side effects. return () => { console.log('componentWillUnmount'); // Lifecycle: Unmount. // Purpost: Clean up things such as event handlers, cancel network request, etc. } }, []); // The array containing props.count is passed to useEffect as its second argument // in the purpose of replacing the useEffect with componentDidUpdate. // The useEffect is tracking the value of props.count, and when it sees a change, the side effect // function is executed. // When the side effect function executes, the logic of checking componentDidUpdate is executed. useEffect(() => { if (!mounted.current) { mounted.current = true; } else { console.log('componentDidUpdate'); // Lifecycle: Update immediately after render. // Purpose: Operate on updated DOM or handle network requests. } }, [props.count]); // The logic of calling function getDerivedStateFromProps. if (prevCount !== props.count) { setDesc(ReactLifecycleHooksOptimization.getDerivedStateFromProps(props, desc)); setPrevCount(props.count); } // Required // Code to display the component. return ( <> {props.count} {desc} </> ) } // Return true if you don't want it to rerender, return false if you want it to render. const shouldComponentUpdate = (prevProps, nextProps) => { console.log('shouldComponentUpdate'); // Lifecycle: Update immediately before render. // Purpose: Allows developer to prevent rendering. return nextProps.count === prevProps.count; }; // The memo higher order component allows you to replace the need for shouldComponentUpdate. // The memo higher order component takes 2 arguments, a component and a comparison function of // prevProps and nextProps. const ReactLifecycleHooksOptimization = memo(ReactLifecycleHooks, shouldComponentUpdate); // Rarely Used Lifecycle // The getDerivedStateFromProps function here is created for the purpose of // using getDerivedStateFromProps in hooks. ReactLifecycleHooksOptimization.getDerivedStateFromProps = (nextProps, prevState) => { console.log(`getDerivedStateFromProps nextProps.count=${nextProps.count} prevState=${prevState}`); // Lifecycle: Mount and update immediately before render. // Purpose: When your state depends on props (should be avoided). if (nextProps.count === 0 || nextProps.count > 1) { return 'users'; } return 'user'; } const Nothing = () => 'Nothing'; const App = () => { const [component, setComponent] = useState(1); const [count, setCount] = useState(1); const Component = component > 0 ? ReactLifecycleHooksOptimization : Nothing; return ( <> <button onClick={() => (console.clear(), setComponent(component > 0 ? 0 : 1))}>Mount/Unmount</button> <button onClick={() => (console.clear(), setCount(count + 1))}>Update value</button> <Component count={count} /> </> ); }; ReactDOM.render(<App />, document.getElementById('app'));
Live demo is available on CodePen.
Note
According to the React docs, getSnapshotBeforeUpdate
, componentDidCatch
and getDerivedStateFromError
, there are no Hook equivalents for these methods yet.
Top comments (0)