Coder Perfect

In React Hooks, how do you use componentWillMount()?

Problem

The official React documentation mentions –

My question is – how can we use the componentWillMount() lifecyle method in a hook?

Asked by Abrar

Solution #1

Any current lifecycle methods (componentDidMount, componentDidUpdate, componentWillUnmount, and so on) cannot be used in a hook. They’re just good for class components. Hooks, on the other hand, can only be used in functional components. The following is taken from the React documentation:

You can use functional components to replicate these lifecycle methods from class components.

When a component is mounted, the code in componentDidMount runs once. This behavior’s useEffect hook equivalent is

useEffect(() => {
  // Your code here
}, []);

Take note of the second argument (empty array). This will only happen once.

The useEffect hook will be invoked on every render of the component if the second parameter is omitted, which can be problematic.

useEffect(() => {
  // Your code here
});

componentWillUnmount is a cleanup component (like removing event listeners, cancel the timer etc). Assume you’re adding a componentDidMount event listener and deleting it in componentWillUnmount, as shown below.

componentDidMount() {
  window.addEventListener('mousemove', () => {})
}

componentWillUnmount() {
  window.removeEventListener('mousemove', () => {})
}

The above code’s hook equivalent will be as follows:

useEffect(() => {
  window.addEventListener('mousemove', () => {});

  // returned function will be called on component unmount 
  return () => {
    window.removeEventListener('mousemove', () => {})
  }
}, [])

Answered by Bhaskar Gyan Vardhan

Solution #2

const useComponentWillMount = (cb) => {
    const willMount = useRef(true)

    if (willMount.current) cb()

    willMount.current = false
}

When there is a sequence problem, this hook could come in handy (such as running before another script). If that’s not the case, useComnponentDidMount, which is more in line with React hooks.

const useComponentDidMount = cb => useEffect(cb, []);

Use this solution if you know your effect should only run once at the start. It will only run once after the component has been installed.

The lifecycle methods of class components are defined as points in the component’s timeline. This is not the case with hooks. Instead, impacts should be organized according to their content.

function Post({postID}){
  const [post, setPost] = useState({})

  useEffect(()=>{
    fetchPosts(postID).then(
      (postObject) => setPost(postObject)
    )
  }, [postID])

  ...
}

The effect in the example above is used to get the content of a post. Instead of a specific point in time, it has a value on which it is based – postID. It will rerun every time postID receives a new value (including initialization).

componentWillMount is considered legacy in the componentWillMount class (source 1, source2). It’s legacy since it might run several times, and there’s a better way to do it: use the constructor. For a functioning component, those issues are irrelevant.

Answered by Ben Carp

Solution #3

componentWillMount will not be maintained in the future, according to reactjs.org. https://reactjs.org/docs/react-component.html#unsafe componentwillmount

It’s not necessary to use componentWillMount.

Simply do something in the constructor if you want to perform something before the component is installed ().

ComponentWillMount is not the place to make network requests. Because doing so will result in unanticipated bugs.

componentDidMount can be used to make network requests.

Hope it helps.

updated on 08/03/2019

You’re presumably asking for componentWillMount because you want to set the state before rendering.

Simply useState to accomplish this.

const helloWorld=()=>{
    const [value,setValue]=useState(0) //initialize your state here
    return <p>{value}</p>
}
export default helloWorld;

Alternatively, if your original code looks like this, you might want to call a function in componentWillMount:

componentWillMount(){
  console.log('componentWillMount')
}

All you have to do with hook is remove the lifecycle method:

const hookComponent=()=>{
    console.log('componentWillMount')
    return <p>you have transfered componeWillMount from class component into hook </p>
}

I’d like to add something to the initial response regarding useEffect.

useEffect(()=>{})

useEffect is a combination of componentDidUpdate, componentDidMount, and ComponentWillUnmount that executes on every render.

 useEffect(()=>{},[])

When we use an empty array in useEffect, the effect is only activated when the component is mounted. It’s because the array you gave to useEffect will be compared. As a result, it is not required to be an empty array. It could be a non-changing array. It may be [1,2,3] or [‘1,2’], for example. useEffect is still only activated when a component is attached.

It is entirely up to you whether you want it to execute only once or after each render. If you know what you’re doing, it’s not harmful if you forget to add an array.

For hook, I made a sample. Please have a look.

https://codesandbox.io/s/kw6xj153wr

updated on 21/08/2019

It’s been a long time since I wrote the above response. I believe there is something to which you should pay attention. When you make use of

useEffect(()=>{},[])

When react compares the values you gave to the array [, it does so using Object.is(). If you provide it an item, such as

useEffect(()=>{},[{name:'Tom'}])

This is the exact same as:

useEffect(()=>{})

Because Object.is() compares an object’s reference rather than the value itself, it will re-render each time. It’s the same reason that === returns false: their references aren’t the same. You can do something like this if you still want to compare the object actually rather than the reference:

useEffect(()=>{},[JSON.stringify({name:'Tom'})])

Update on 7/09/2021:

A couple more changes on the dependency:

When you utilize a function or object as a dependency, it will almost always re-render. However, react already has a solution for you: useMemo and useCallback

useCallback has the ability to remember a function. useMemo has the ability to remember an object.

See this article:

https://javascript.plainenglish.io/5-useeffect-infinite-loop-patterns-2dc9d45a253f

Answered by MING WU

Solution #4

To emulate a componentWillMount lifecycle event, you can use the useMemo hook. Simply put:

const Component = () => {
   useMemo(() => {
     // componentWillMount events
   },[]);
   useEffect(() => {
     // componentDidMount events
     return () => {
       // componentWillUnmount events
     }
   }, []);
};

Keep the useMemo hook in front of anything that interacts with your state. This is not how it is intended but it worked for me for all componentWillMount issues.

This works because useMemo does not need you to return a value or use it as anything, but because it memorizes a value based on dependencies that will only run once (“[]”) and is on top of our component, it runs once when the component mounts before anything else.

Answered by jpmarks

Solution #5

Follow this graphic for a quick visual reference.

As you can see in the following image, you must perform something similar for ComponentWillUnmount.

 useEffect(() => {
    return () => {
        console.log('componentWillUnmount');
    };
   }, []);

Answered by lokender singh

Post is based on https://stackoverflow.com/questions/53464595/how-to-use-componentwillmount-in-react-hooks