5

I'v taken a look here but the selected answer does not answer the question. I'm looking for a componentWillMount() equivalent to execute logic similar to:

useEffect(() => {
  if (condition) {
    // do stuff
  }
}, []);

The issue with the above is that the component renders for a split second before executing the useEffect block of code.

Any way to get around this? Without having the useEffect run in the main App component or creating a custom hook?

Mike K
  • 7,621
  • 14
  • 60
  • 120
  • How about using `componentWillUpdate()` itself? – displayName Aug 06 '19 at 10:51
  • 2
    I don't want to use class-based components – Mike K Aug 06 '19 at 10:52
  • have you looked into `useLayoutEffect`? https://reactjs.org/docs/hooks-reference.html#uselayouteffect Still not exactly what you want, but closer than `useEffect`. – Clarity Aug 06 '19 at 10:55
  • 2
    Im curious why do you need `componentWillMount` over `didMount` or `didUpdate`. React team has explained alot of times why this is a bad idea to do things in blocking the UI thread. I think you just need to find a better way of doing it. If you have a small example I'm sure we can help with finding a solution – Umair Ahmed Aug 06 '19 at 11:11
  • 4
    There is no cwm equality in hooks if you specify your problem, maybe we can suggest another solution. – Kaan Öner Aug 06 '19 at 11:12
  • @MikeK [Read my answer](https://stackoverflow.com/questions/53464595/how-to-use-componentwillmount-in-react-hooks/60866524#60866524), it could help you. – Jiri Mihal Mar 26 '20 at 12:26

3 Answers3

4

From reactjs docs:

This lifecycle was previously named componentWillMount. That name will continue to work until version 17. Use the rename-unsafe-lifecycles codemod to automatically update your components.

UNSAFE_componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering. Generally, we recommend using the constructor() instead for initializing state.

So there is no more equivalent for componentWillMount, you can modify render method to return null/placeholder until your init conditions are met and set state in useEffect. You can look into react suspense too.

hidden_4003
  • 1,759
  • 2
  • 14
  • 20
2

you could transform your component into a class or you could do a workaround like this:

let firstRender = true
const yourComponent = () =>{
  useEffect(() =>{
    firstRender = false
  },[])
  if (firstRender){
   // willmount code
  }
  return null
}
benomatis
  • 5,536
  • 7
  • 36
  • 59
  • A component shouldn't look like this. It would be better if `firstRender` were a State because 1) You're using a variable from outside the component (and it isn't a prop); 2) This won't trigger a second render, so your "`willmount code`" can mean "`didmount code`" – Rafael Tavares Oct 09 '20 at 11:05
2

It's too late for you, but maybe will help the others

There's no equivalent of ComponentWillMount for hooks, BUT you can simulate the behavior by creating a hook and using useRef like this

export const useWillMount = (fn) => {
  const willMount = useRef(true)
  
  if (willMount.current && fn && typeof fn === 'function') {
    fn()
  }
  
  willMount.current = false
}

Usage

const Component = (props) => {
  useWillMount(() => {
    // Do stuff for componentWillMount here
  })

  ...
}

herlambang
  • 158
  • 1
  • 1
  • 7
  • Yeah, I remember finding a similar answer [here](https://stackoverflow.com/a/56818036/2891356), but then I realized that this will not work with SSR (Nextjs), so I ended up refactoring. – Mike K Feb 07 '21 at 09:40