Concerning the newly proposed React Effect Hook;
What are the advantages and use cases of the Effect
hook (useEffect()
)?
Why would it be preferable & how does it differ over componentDidMount/componentDidUpdate/componentWillUnmount
(performance/readability)?
The documentation states that:
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase).
but I think it was already common knowledge to have these behaviors in lifecycle methods like componentDidUpdate, etc. instead of the render method.
There's also the mention that:
The function passed to useEffect will run after the render is committed to the screen.
but isn't that what componentDidMount
& componentDidUpdate
do anyways?
The useEffect Hook allows you to perform side effects in your components. Some examples of side effects are: fetching data, directly updating the DOM, and timers.
The useState hook is used for storing variables that are part of your application's state and will change as the user interacts with your website. The useEffect hook allows components to react to lifecycle events such as mounting to the DOM, re-rendering, and unmounting.
The warning “React Hook useEffect has a missing dependency” occurs when the useEffect hook makes use of a variable or function outside its scope that we haven't included inside its dependency array.
Using useEffect is probably the best part of React Hooks. It helps reduce the clutter of the component lifecycle methods and, most importantly, it helps separate different logic that can appear in the lifecycle methods.
What are the advantages and use cases of the
Effect
hook (useEffect()
)?
Primarily, hooks in general enable the extraction and reuse of stateful logic that is common across multiple components without the burden of higher order components or render props.
A secondary benefit (of Effect hooks in particular) is the avoidance of bugs that might otherwise arise if state-dependent side effects are not properly handled within componentDidUpdate
(since Effect hooks ensure that such side effects are setup and torn-down on every render).
See also the peformance and readability benefits detailed below.
Any component that implements stateful logic using lifecycle methods—the Effect hook is a "Better Way".
Why would it be preferable & how does it differ over
componentDidMount
/componentDidUpdate
/componentWillUnmount
(performance/readability)?
Because of the advantages detailed above and below.
Effect hooks—
Effect hooks result in:
simpler and more maintainable components, owing to an ability to split unrelated behaviour that previously had to be expressed across the same set of lifecycle methods into a single hook for each such behaviour—for example:
componentDidMount() { prepareBehaviourOne(); prepareBehaviourTwo(); } componentDidUnmount() { releaseBehaviourOne(); releaseBehaviourTwo(); }
becomes:
useEffect(() => { prepareBehaviourOne(); return releaseBehaviourOne; }); useEffect(() => { prepareBehaviourTwo(); return releaseBehaviourTwo; });
Notice that code relating to BehaviourOne
is now distinctly separated from that relating to BehaviourTwo
, whereas before it was intermingled within each lifecycle method.
less boilerplate, owing to an elimination of any need to repeat the same code across multiple lifecycle methods (such as is common between componentDidMount
and componentDidUpdate
)—for example:
componentDidMount() { doStuff(); } componentDidUpdate() { doStuff(); }
becomes:
useEffect(doStuff); // you'll probably use an arrow function in reality
Here is an example from ReactConf2018 Dan Abramov's talk explaining the difference:
Here are the few findings from the below example:
useEffect()
Unlike componentDidMount and componentDidUpdate, the function passed to useEffect fires after layout and paint, during a deferred event
useEffect()
hook that is very effective when you just pass empty array [] to render component on only mounting and unmounting.useEffect()
hooks to Separate Concerns and react will:Hooks lets us split the code based on what it is doing rather than a lifecycle method name. React will apply every effect used by the component, in the order they were specified
Using Classes:
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
Using Hooks:
import { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With