How to use componentWillMount() in React Hooks?
Asked Answered
A

21

433

In the official docs of React it mentions -

If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

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

Astoria answered 25/11, 2018 at 4:13 Comment(0)
J
752

You cannot use any of the existing lifecycle methods (componentDidMount, componentDidUpdate, componentWillUnmount etc.) in a hook. They can only be used in class components. And with Hooks you can only use in functional components. The line below comes from the React doc:

If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

suggest is, you can mimic these lifecycle method from class component in a functional components.

Code inside componentDidMount run once when the component is mounted. useEffect hook equivalent for this behaviour is

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

Notice the second parameter here (empty array). This will run only once.

Without the second parameter the useEffect hook will be called on every render of the component which can be dangerous.

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

componentWillUnmount is use for cleanup (like removing event listeners, cancel the timer etc). Say you are adding a event listener in componentDidMount and removing it in componentWillUnmount as below.

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

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

Hook equivalent of above code will be as follows

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

  // returned function will be called on component unmount 
  return () => {
    window.removeEventListener('mousemove', () => {})
  }
}, [])
Jumpy answered 25/11, 2018 at 6:26 Comment(18)
Nice explanation for other Lifecycle events, but this doesn't the question specifically about an alternative to componentWillMount().Osculate
In the PanResponder examples I've seen componentWillMount seems to be required, otherwise you get undefined panHandlers.Mosenthal
Note the [] as the second argument to useEffect. Without it, you end up with the effect being ran on every render, not just the first render. Since [] is the same every time, React thinks the effect has been applied already (read: dynamic programming/memoization at play), and doesn't re-run your function.Zaidazailer
And what if we do not need componentDidMount and would like just need to use componentWillUnmount alternative in functional component?Ellipsoid
I now really understand the useEffect() function, thanks.Nuzzle
Thank you this helped me cleanup an image slider component that used setInterval to change the slides. It needed to clearInterval on component dismount.Ranit
Why is this an accepted answer?? You didn't mention a hook equivalent for componentWillMountArbogast
Those who say that he didn't mention "componentWillUnmount" equivalent aren't paying attention, specifically to the "return" statement of the useEffect hook, which is where you can do all the 'unmounting' related tasksJemison
@Jemison The question asked for an equivalent to componentWillMount, not componentWillUnmount. This answer indeed does not answer the question at all, and just re-iterates what the OP already implied to know.Deaconry
In case I use the last option, the empty array, what do I do if I want to read a state but it keeps complaining that I should add it to the dependency array? I want only to run the code when the component is unmounting.Toady
@Deaconry ..I see, my mistake. But either way componentWillMount was deprecated back in 2018. You can do just about any initialization and other calculations in the function component before the return() statement.. The same thing as you can do in the class constructor. Makes componentWillMount somewhat redundant, imoJemison
@Jemison Actually, any code in a function component before the return statement will in fact be executed every time the component is rendered, not just the first time as the constructor (or previously componentWillMount) would be used for. @Ben Carp's answer is the highest voted answer that actually answers the question.Deaconry
this answer is MUCH better than the many silly articles out there. Thank you so very much for the concise answer.Crum
I think the event handler for 'mousmove' defined in the remove and addEvent part are different due to ()=>{} creating 2 different function references. Hence that might cause a bug.Leukocyte
sometime we need to set a state in componentWillMount, without this, it will cost the component render twice, especially if u are running many layer component, u will render twice for all component, if u cant use componentWillMount on the top layer (assume you need)Bifrost
Ironically, I found this when looking for info about a hook version of componentWillUnmount, even though the original question is about componentWillMount. So, while it is a useful answer for me, this does not answer the original question. Not sure why this is the accepted answer, or why it has so many up-votes.Epicanthus
For people looking for an actual answer to the question that was asked, see #53465095 or the blog post dev.to/video/…, since using useEffect very much is NOT equivalent to componentWillMount.Kuehl
This answer is awful - it doesn't respond to the question in any way whatsoever - it doesn't even bother to mention "componentWillMount"Biblical
S
251

useComponentWillMount hook

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

    if (willMount.current) cb()

    willMount.current = false
}

This hook could be a saver when there is an issue of sequence (such as running before another script). If that isn't the case, use useComnponentDidMount which is more aligned with React hooks paradigm.

useComponentDidMount hook

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

If you know your effect should only run once at the beginning use this solution. It will run only once after component has mounted.

useEffect paradigm

Class components have lifecycle methods which are defined as points in the timeline of the component. Hooks don't follow this paradigm. Instead effects should be structured by their content.

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

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

  ...
}

In the example above the effect deals with fetching the content of a post. Instead of a certain point in time it has a value it is dependent on - postID. Every time postID gets a new value (including initialization) it will rerun.

Component Will Mount discussion

In class components componentWillMount is considered legacy (source 1, source2). It's legacy since it might run more than once, and there is an alternative - using the constructor. Those considerations aren't relevant for a functional component.

Swig answered 29/6, 2019 at 13:44 Comment(16)
This is the only answer that answers the question and makes sense. Thank you!Revelatory
The only problem with that is you get an extra render because of the state update involved. By using a ref instead you get the desired behavior without the extra render: ` const useComponentWillMount = func => { const willMount = useRef(true); useEffect(() => { willMount.current = false; }, []); if (willMount.current) { func(); } }; `Suggestible
This functional implementation of componentWillMount based on useEffect has two problems. The first one is that there isn't a mounting lifecycle in functional components, both hooks will run after the component has rendered, so Runs only once before component mounts is misleading. The second one is that componentWillMount is called on server rendering and useEffect is not. Many libraries still rely on UNSAFE_componentWillMount because currently it's the only way to trigger a side-effect server-side.Elwin
@PaoloMoretti, thanks. This componentWillMount hook, isn't the exact equivalent of componentWillMount lifecycle in a class component. However, the function that is passed to it, will run immediately, only the first time it is called. This practially means it will run before it is rendered, and before it even returns a value for the first time. Can we agree about that? I agree that using the name componentWillMount isn't ideal, since this name carries certain meaning from the class lifecycle version. Perhaps I better call it "useRunPreMount".Swig
I'm, sorry I actually didn't realize that the useComponentWillMount callback runs on the first invocation. In that case, what I said about the first problem is wrong, I think it's possibly the closest implementation of componentWillMount with hooks. The second problem is still valid, because useEffect does not run in SSR, so I think it will always execute the callback, since willMount.current won't be set to false by useEffect.Elwin
@PaoloMoretti, I don't quite get it. I don't work with SSR, but my undertstanding is that on SSR componentWillMount runs twice - once on the server and once on the client. I think the same is true for the callback that is passed to useComponentDidMount. useComponentDidMount relays on useEffect to stop invocing the callback. Until useEffect's callback is executed the component's function will run twice - once on the server and once on the client. Isn't that the case?Swig
Thank you for these snippets! These should be built in hooks to React. The semantic advantage of having hooks the easily describe what they are doing is still a void left in the wake of leaving behind class components IMO. I think hooks and functional components are the way to go no doubt, but the useEffect equivalent of componentDidMount is ugly and unless someone knows React well, will be confusing. The React team should have included something similar to this!Skein
I agree that this is the only correct answer to the question. My use case was wanting to do a one-time pre-render action. Using useRef will indeed accomplish this (as will the custom ref provided here). Thank you!Deaconry
Only one thing. I would use the intended function useState for storing values instead of useRef which is intended for referencing the DOM of a component.Forbear
@JiriMihal see remix23 comment above. Originally I used useState and remix23 suggested useRef. I think he has a point. I think useRef is intended for dom references, but not only for this purpose.Swig
@BenCarp I see it, it makes sense. I noticed one more thing. willMount.current = false; should be right after func();. If func(); changes component state, you will get an infinite loop.Forbear
@JiriMihal, Nice catch. Thx! I fixed my answer. Luckily, such a situation is noticeable (if someone passes a callback that updates state an infinite loop must occur and an error will show) and therefor isn't likely to get to production.Swig
@BenCarp, thank you so much for the the explanation and demo. I've been looking for an answer to componentWillMount implementation using hooks and your's works perfectly. :)Ifc
What would happen if you implement the useComponentWillMount hook with useMemo instead of useEffect ??Muzzy
@norman123123, As far as I can tell it will work exactly the same.Swig
Your useRef example is great, but the React docs specifically say not to use useMemo for this purpose. You may rely on useMemo as a performance optimization, not as a semantic guarantee. reactjs.org/docs/hooks-reference.html#usememoThirlage
B
76

According to reactjs.org, componentWillMount will not be supported in the future. https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

There is no need to use componentWillMount.

If you want to do something before the component mounted, just do it in the constructor().

If you want to do network requests, do not do it in componentWillMount. It is because doing this will lead to unexpected bugs.

Network requests can be done in componentDidMount.

Hope it helps.


updated on 08/03/2019

The reason why you ask for componentWillMount is probably because you want to initialize the state before renders.

Just do it in useState.

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

or maybe You want to run a function in componentWillMount, for example, if your original code looks like this:

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

with hook, all you need to do is to remove the lifecycle method:

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

I just want to add something to the first answer about useEffect.

useEffect(()=>{})

useEffect runs on every render, it is a combination of componentDidUpdate, componentDidMount and ComponentWillUnmount.

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

If we add an empty array in useEffect it runs just when the component mounted. It is because useEffect will compare the array you passed to it. So it does not have to be an empty array.It can be array that is not changing. For example, it can be [1,2,3] or ['1,2']. useEffect still only runs when component mounted.

It depends on you whether you want it to run just once or runs after every render. It is not dangerous if you forgot to add an array as long as you know what you are doing.

I created a sample for hook. Please check it out.

https://codesandbox.io/s/kw6xj153wr


updated on 21/08/2019

It has been a while since I wrote the above answer. There is something that I think you need to pay attention to. When you use

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

When react compares the values you passed to the array [], it uses Object.is() to compare. If you pass an object to it, such as

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

This is exactly the same as:

useEffect(()=>{})

It will re-render every time because when Object.is() compares an object, it compares its reference, not the value itself. It is the same as why {}==={} returns false because their references are different. If you still want to compare the object itself not the reference, you can do something like this:

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

Update on 7/09/2021:

A few updates about the dependency:

Generally speaking, if you use a function or an object as a dependency, it will always re-render. But react already provides you with the solution: useCallback and useMemo

useCallback is able to memorize a function. useMemo is able to memorize an object.

See this article:

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

Bove answered 25/11, 2018 at 4:20 Comment(6)
and the question was how to implement it with hooksWakeen
but you do not need to implement it with hooks because it will not be supported. No need to learn how to do that with hooks.Bove
Now that you have mentioned that componentDidMount is the correct lifecycle to use, you could have added how to implement that in your answer and then your answer would make more sense than the accepted answerWakeen
that is right. Thanks for pointing it out. I will add it later this week.Bove
Surely this should be the accepted answer - it explains that ComponentWillMount is not available in the hooks paradigm. Initialisation in functional components is simplified - it just needs to be part of the functionOsculate
How is this the same thing as componentWillMount? If you throw code into the functional component then it will run every single render, not only when the component is about to mount.Tervalent
C
34

React Lifecycle methods in hooks

for simple visual reference follow this image

enter image description here

As you can simply see in the above picture that for ComponentWillUnmount, you have to do like this

 useEffect(() => {
    return () => {
        console.log('componentWillUnmount');
    };
   }, []);
Centiliter answered 23/12, 2020 at 16:8 Comment(4)
Thank you! Could you put here a link to the original article/post? The quality of picture is bad [картинка шакального качества].Quinacrine
Question is for componentWillMount, not componentWillUnmountEarache
Image source: twitter.com/siddharthkmr1/status/1294733239429369857Passable
Epic ! Thanks a lot , I was searching a lot for unmount hookMaier
T
27

You can hack the useMemo hook to imitate a componentWillMount lifecycle event. Just do:

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

You would need to keep the useMemo hook before 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 doesnt require to actually return a value and you dont have to actually use it as anything, but since it memorizes a value based on dependencies which will only run once ("[]") and its on top of our component it runs once when the component mounts before anything else.

Tarnetgaronne answered 2/7, 2020 at 17:14 Comment(2)
This might work with the current implementation, but the React docs specifically say not to do this. You may rely on useMemo as a performance optimization, not as a semantic guarantee. reactjs.org/docs/hooks-reference.html#usememoThirlage
I agree. It's slightly risky, but if you use it carefully you can get what you are looking for. I find it useful for initializing things that are independent from the components rendering status.Tarnetgaronne
A
24

useLayoutEffect could accomplish this with an empty set of observers ([]) if the functionality is actually similar to componentWillMount -- it will run before the first content gets to the DOM -- though there are actually two updates but they are synchronous before drawing to the screen.

for example:


function MyComponent({ ...andItsProps }) {
     useLayoutEffect(()=> {
          console.log('I am about to render!');
     },[]);

     return (<div>some content</div>);
}

The benefit over useState with an initializer/setter or useEffect is though it may compute a render pass, there are no actual re-renders to the DOM that a user will notice, and it is run before the first noticable render, which is not the case for useEffect. The downside is of course a slight delay in your first render since a check/update has to happen before painting to screen. It really does depend on your use-case, though.

I think personally, useMemo is fine in some niche cases where you need to do something heavy -- as long as you keep in mind it is the exception vs the norm.

Aerobiology answered 19/4, 2019 at 21:34 Comment(5)
useLayoutEffect is the way to go!!!! This answer my question regarding checking if the user is logged in. (The problem was, the components would load, then check if user is logged in.) My question is though, is this standard practice? I'm not seeing at too many placesSausa
yeah it's pretty common; mentioned in official React docs as well -- just in smaller text because of the ramifications of double DOM render in order to run logic before a user notices.Aerobiology
Actually it runs after rendering the component. So it's totally different than componentWillMount.Forbear
As @JiriMihal mentioned, useLayoutEffect runs after rendering, from React Docs (reactjs.org/docs/hooks-reference.html#uselayouteffect): If you’re migrating code from a class component, note useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate.Earache
@Earache late reply but directly from docs: useLayoutEffect is a version of useEffect that fires before the browser repaints the screen. Usage: Measuring layout before the browser repaints the screen In practice it substitutes most use-cases that are not anti-patterns of previous class based paradigms.Aerobiology
F
21

This is the way how I simulate constructor in functional components using the useRef hook:

function Component(props) {
    const willMount = useRef(true);
    if (willMount.current) {
        console.log('This runs only once before rendering the component.');
        willMount.current = false;        
    }

    return (<h1>Meow world!</h1>);
}

Here is the lifecycle example:

function RenderLog(props) {
    console.log('Render log: ' + props.children);
    return (<>{props.children}</>);
}

function Component(props) {

    console.log('Body');
    const [count, setCount] = useState(0);
    const willMount = useRef(true);

    if (willMount.current) {
        console.log('First time load (it runs only once)');
        setCount(2);
        willMount.current = false;
    } else {
        console.log('Repeated load');
    }

    useEffect(() => {
        console.log('Component did mount (it runs only once)');
        return () => console.log('Component will unmount');
    }, []);

    useEffect(() => {
        console.log('Component did update');
    });

    useEffect(() => {
        console.log('Component will receive props');
    }, [count]);


    return (
        <>
        <h1>{count}</h1>
        <RenderLog>{count}</RenderLog>
        </>
    );
}
[Log] Body
[Log] First time load (it runs only once)
[Log] Body
[Log] Repeated load
[Log] Render log: 2
[Log] Component did mount (it runs only once)
[Log] Component did update
[Log] Component will receive props

Of course Class components don't have Body steps, it's not possible to make 1:1 simulation due to different concepts of functions and classes.

Forbear answered 26/3, 2020 at 11:45 Comment(3)
I didn't dive into your example but your first code snippet works for me, Thank you!Immediate
Precise and simple.Muzzy
sorry, how do you guarantee that the things inside the "if" runs before the func component get mount to dom?Nightie
N
7

I wrote a custom hook that will run a function once before first render.

useBeforeFirstRender.js

import { useState, useEffect } from 'react'

export default (fun) => {
  const [hasRendered, setHasRendered] = useState(false)

  useEffect(() => setHasRendered(true), [hasRendered])

  if (!hasRendered) {
    fun()
  }
}

Usage:

import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'


export default () => { 
  useBeforeFirstRender(() => {
    console.log('Do stuff here')
  })

  return (
    <div>
      My component
    </div>
  )
}
Nuclease answered 17/7, 2019 at 10:12 Comment(1)
This will cause a re-render because of changing stateEarache
K
5

Given that

  • componentWillMount is deprecated (1, 2, 3), and that the suggested replacement is executing code in the constructor
  • in a functional component, code executed before the return statement is implicitly run before rendering it
  • the rough equivalent of mounting a class component is the initial call of a functional component
  • the goal is to execute a piece of code once, before the DOM ui is updated, and never run the code again for as long as the component remains "mounted"

The solution would be

Running a function in the body of the functional component only once. Since code in the body of a functional component is normally run on every re-render, we need to turn to hooks. The options are useState, useMemo, or useEffect, depending on the timing required for the use case.

Since the code needs to run before the initial render is committed to the screen, this disqualifies useEffect: “The function passed to useEffect will run after the render is committed to the screen.” 4.

Since we want to guarantee that the code will only run once and not be recalculated, this disqualifies useMemo: "In the future, React may choose to “forget” some previously memoized values and recalculate them on next render" 5.

useState supports lazy initial state calculations that are guaranteed to run only once when a functional component is first rendered, which is exactly what we're looking for.

Example with useState

const runOnceBeforeRender = () => {};

const Component = () => {
  useState(runOnceBeforeRender);

  return (<></>);
}

As a custom hook

const runOnceBeforeRender = () => {};

const useOnInitialRender = (fn) => {
  useState(fn);
}

const Component = () => {
  useOnInitialRender(runOnceBeforeRender);

  return (<></>);
};

The runOnceBeforeRender function can optionally return a value that will be available immediately upon the first render of the function, triggering no re-renders. The value won't be recalculated on subsequent renders.

const runOnceBeforeRender = () => 1 + 1;

const useOnInitialRender = (fn) => {
  const [value] = useState(fn);

  return value;
}

const Component = () => {
  const value = useOnInitialRender(runOnceBeforeRender);

  return (<>{value}</>); // 2
};

A (probably unnecessary) NPM package: useOnce hook

Kuehl answered 29/4, 2021 at 9:56 Comment(0)
A
1

Ben Carp's answer seems like only valid one to me.

But since we are using functional ways just another approach can be benefiting from closure and HoC:

const InjectWillmount = function(Node, willMountCallback) {
  let isCalled = true;
  return function() {
    if (isCalled) {
      willMountCallback();
      isCalled = false;
    }
    return Node;
  };
};

Then use it :

const YourNewComponent = InjectWillmount(<YourComponent />, () => {
  console.log("your pre-mount logic here");
});
Adigranth answered 22/12, 2019 at 12:44 Comment(0)
M
1

It might be clear for most, but have in mind that a function called inside the function component's body, acts as a beforeRender. This doesn't answer the question of running code on ComponentWillMount (before the first render) but since it is related and might help others I'm leaving it here.

const MyComponent = () => {
  const [counter, setCounter] = useState(0)
  
  useEffect(() => {
    console.log('after render')
  })

  const iterate = () => {
    setCounter(prevCounter => prevCounter+1)
  }

  const beforeRender = () => {
    console.log('before render')
  }

  beforeRender()

  return (
    <div>
      <div>{counter}</div>
      <button onClick={iterate}>Re-render</button>
    </div>
  )
}

export default MyComponent
Mattos answered 2/11, 2020 at 14:21 Comment(0)
U
0

https://reactjs.org/docs/hooks-reference.html#usememo

Remember that the function passed to useMemo runs during rendering. Don’t do anything there that you wouldn’t normally do while rendering. For example, side effects belong in useEffect, not useMemo.

Urbano answered 10/2, 2019 at 15:20 Comment(2)
usememo is for performance optimization. A hook will be rendered again after being already mounted if a prop change, which defeat the purpose of the author.Abbacy
A hook does not render, a hook will cause a component to re-render. Hooks are also not dependent on props, they are simply tools to manage state and component lifecycle events using side effects.Rap
T
0

There is a nice workaround to implement componentDidMount and componentWillUnmount with useEffect.

Based on the documentation, useEffect can return a "cleanup" function. this function will not be invoked on the first useEffect call, only on subsequent calls.

Therefore, if we use the useEffect hook with no dependencies at all, the hook will be called only when the component is mounted and the "cleanup" function is called when the component is unmounted.

useEffect(() => {
    console.log('componentDidMount');

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

The cleanup return function call is invoked only when the component is unmounted.

Hope this helps.

Thundersquall answered 10/11, 2019 at 11:29 Comment(4)
How does this help if it has nothing to do with componentWillMount? Am I missing something?Harvard
Yes, you are missing the fact that in the same useEffect call you get the same functionality of componentWillMount and componentWillUnmount in a nice and clean wayThundersquall
That's not true, useEffect only runs after a render while componentWillMount runs before the component renders.Tervalent
@Tervalent I was talking about componentDidMount not componentWillMount. I missed that in the question, my bad.Thundersquall
W
0

Short answer to your original question, how componentWillMount can be used with React Hooks:

componentWillMount is deprecated and considered legacy. React recommendation:

Generally, we recommend using the constructor() instead for initializing state.

Now in the Hook FAQ you find out, what the equivalent of a class constructor for function components is:

constructor: Function components don’t need a constructor. You can initialize the state in the useState call. If computing the initial state is expensive, you can pass a function to useState.

So a usage example of componentWillMount looks like this:

const MyComp = () => {
  const [state, setState] = useState(42) // set initial value directly in useState 
  const [state2, setState2] = useState(createInitVal) // call complex computation

  return <div>{state},{state2}</div>
};

const createInitVal = () => { /* ... complex computation or other logic */ return 42; };
Wheatear answered 7/3, 2020 at 11:41 Comment(0)
T
0

As it has been stated in react document:

You might be thinking that we’d need a separate effect to perform the cleanup. But code for adding and removing a subscription is so tightly related that useEffect is designed to keep it together. If your effect returns a function, React will run it when it is time to clean up:

useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

so the only thing that we need to have the componentWillUnmount in hooks is to return a function inside a useEffect, as explained above.

Tropophilous answered 22/2, 2021 at 11:50 Comment(0)
V
0

So for React hooks, I think declaring your logic before the return statement can work. You should have a state that is set to true by default. In my case, I called the state componentWillMount. Then a conditional to run a block of code when this state is true (the block of code contains the logic you want executed in your componentWillMount), the last statement in this block should be resetting the componentWillMountState to false (This step is important because if it is not done, infinite rendering will occur) Example

// do your imports here

const App = () =>  {
  useEffect(() => {
    console.log('component did mount')
  }, [])
  const [count, setCount] = useState(0);
  const [componentWillMount, setComponentWillMount] = useState(true);
  if (componentWillMount) {
    console.log('component will mount')
    // the logic you want in the componentWillMount lifecycle
    setComponentWillMount(false)
  }
  
  return (
    <div>
      <div>
      <button onClick={() => setCount(count + 1)}> 
        press me
      </button>
      <p>
        {count}
      </p>
      
      </div>
    </div>
  )
}
Vocalist answered 25/6, 2021 at 17:42 Comment(0)
M
0

This might not be the exact alternative to the componentWillMount method but here is a method that can be used to achieve the same objective but by using useEffect :

First initialize the object where you retrive the data to an empty value and define the useEffect method:

const [details, setDetails] = useState("")

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

const retrieveData = () => {       
       getData()                  // get data from the server 
      .then(response => {
        console.log(response.data);
        setDetails(response.data)
      })
      .catch(e => {
        console.log(e);
      })
  }

Now in the JSX where we return add a terenary operator

*return(
  <div>
    { 
   details ? (
   <div class="">
   <p>add Your Jsx Here</p>
</div>
): (
  <div>
<h4>Content is still Loading.....</h4>
</div>
)
}
  </div>
)*

This will ensure that until the object 'details' has data in it the second part of the terenary operator is loaded which inturn triggers the useEffect method that leads to setting the data received from the server in the 'details' object, hence the rendering of the primary JSX

Mcgruter answered 16/7, 2021 at 18:31 Comment(0)
A
0

We recently had problem with this because we need to do something when a component will mount, that is we need to update the global state.

So I created this hook, not sure how good of an approach this is but so far it works as long as we use this sparingly and only for simple tasks. I probably would not use this for network requests and other long-running and complex tasks.

import { useRef } from 'react';

function useComponentWillMount(callback: () => void) {
  const hasMounted = useRef(false);

  if (!hasMounted.current) {
    (() => {
      hasMounted.current = true;
      callback();
    })();
  }

  console.log(hasMounted.current);
  return null;
}

export default useComponentWillMount;
Apodictic answered 4/3, 2022 at 4:54 Comment(0)
H
0

componentWillMount is deprecated (as mentioned in other comments), the reason for it I think it's very easy to be handled by a simple HOC.

const withComponentWillMount = (WrappedComponent, handler) => {
  return (props) => {
    return handler(props) ? <WrappedComponent {...props} /> : null;
  }
}

I usually implement this solution for my projects. With this HOC, if handler returned false, there is nothing run inside component, included hooks.

Howlend answered 4/10, 2022 at 4:56 Comment(0)
B
-1

React component is a function right? So just let componentWillMount moment be the function body before return statement.

function componentWillMountMomentIsHere() {
  console.log('component will mount')
}


function AnyComponent(){
  const [greeting, setGreeting] = useState('Hello')

  componentWillMountMomentIsHere()

  
  return <h1>{greeting}</h1>
}
Butchery answered 26/8, 2021 at 14:7 Comment(0)
S
-6

Just simply add an empty dependenncy array in useEffect it will works as componentDidMount.

useEffect(() => {
  // Your code here
  console.log("componentDidMount")
}, []);
Shebashebang answered 5/5, 2020 at 13:22 Comment(1)
This is not an answer. The question was about how to use componentWillMount with Hooks.Muzzy

© 2022 - 2024 — McMap. All rights reserved.