Mirodinho
Mirodinho

Reputation: 1321

React hooks: What/Why `useEffect`?

Concerning the newly proposed React Effect Hook;

  1. What are the advantages and use cases of the Effect hook (useEffect())?

  2. 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?

Upvotes: 35

Views: 18229

Answers (4)

john
john

Reputation: 37

useEffect helps to store data in localstorage. See the below example that shows the local data in chrome. Run the code in VS Code and then you can see the data stored under Storage > Local storage by pressing F12 button.

If you comment the useEffect code and then if you refresh chrome browser then the data stored in localstorage will get removed. Hope this helps.

App.jsx file

import ExampleThree from "./components/ExampleThree"

const App = () => {
return <div>
<ExampleThree />
</div>
}

export default App

ExampleThree.jsx file

import React, { useEffect, useState } from 'react'

const ExampleThree = () => {
const [name, setName] = useState(() => {
    const savedName = localStorage.getItem('name')
    return savedName ? JSON.parse(savedName) : ''
})
useEffect(() => {
    localStorage.setItem('name', JSON.stringify(name))
}, [name])

const handleChange = (event) => {
    setName(event.target.value)
}

const handleClear = () => setName("")

return (
    <div>
        <h1>Name: {name}</h1>
        <input type="text" value={name} onChange={handleChange} placeholder="Enter your name"></input>
        <button onClick={handleClear}>Clear Name</button>
    </div>
)
}
export default ExampleThree

Upvotes: 0

Salah
Salah

Reputation: 623

useEffect runs when a state changed.

import { useState, useEffect } from 'react';
function Example() {
  const [Age, setAge] = useState(33);
  const [Somestate,setSomestate]=useState(initilaestate);
  useEffect(() => {
    console.log('the age is changed to ',Age);
  });

// you can use useEffect as many times you want in you component 
  useEffect(() => {
    console.log('the age is changed to ',Age);
  },[someState]);//here you tell useEffect what state to watch if you want to watch the changing of a  particular state and here we care about someState
  return (
    <div>
      <p>age increased to  {Age}</p>
      <button onClick={() => setAge(count + 1)}>
       Increase age by One
      </button>
    </div>
  );
}
```

Upvotes: 4

eggyal
eggyal

Reputation: 125835

  1. What are the advantages and use cases of the Effect hook (useEffect())?

    Advantages

    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.

     

    Use cases

    Any component that implements stateful logic using lifecycle methods—the Effect hook is a "Better Way".

     

  2. Why would it be preferable & how does it differ over componentDidMount/componentDidUpdate/componentWillUnmount (performance/readability)?

    Why it's preferable

    Because of the advantages detailed above and below.

     

    How it differs from lifecycle methods

    Performance

    Effect hooks—

    • feel more responsive than lifecycle methods because they don't block the browser from updating the screen;
    • will however setup and tear-down side effects on every render, which could be expensive…
    • …so can be optimised to be skipped entirely unless specific state has been updated.

     

    Readability

    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
      

Upvotes: 22

Sakhi Mansoor
Sakhi Mansoor

Reputation: 8102

Here is an example from ReactConf2018 Dan Abramov's talk explaining the difference:


Here are the few findings from the below example:

  1. You'll writing less boilerplate code using hooks
  2. Accessing lifecycles updates and states updates with useEffect()
  3. Regarding performace one aspect is:

Unlike componentDidMount and componentDidUpdate, the function passed to useEffect fires after layout and paint, during a deferred event

  1. Code sharing will too much easy and useEffect() can be implemented multiple times for different purposes within the same component.
  2. you can control component re render more efficiently by passing an array as second argument to useEffect() hook that is very effective when you just pass empty array [] to render component on only mounting and unmounting.
  3. Use Multiple 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>
  );
}

Upvotes: 16

Related Questions