10

For react class component, we have the componentWillMount() lifecycle method, where we can perform tasks before loading the component. Tasks like, a call to backend and use the response to show that data in that frontend.

What if I want the same thing in a functional component? Like I have used react chartJS and for that the data values I want to be retrieved from backend response, and then the chart will populate based on those datas.

Pang
  • 9,564
  • 146
  • 81
  • 122
kushal verma
  • 135
  • 1
  • 2
  • 11
  • 2
    1) [`componentWillMount` has been deprecated](https://reactjs.org/docs/react-component.html#unsafe_componentwillmount) and should not be used even in class components. 2). You're looking for [`useEffect`](https://reactjs.org/docs/hooks-effect.html). – Brian Thompson May 29 '20 at 17:07
  • 2
    The best you can do is emulate `componentDidMount` by using an empty dependency array for `useEffect`. – 101arrowz May 29 '20 at 17:09

2 Answers2

30

componentWillMount is call only one time before initial render. I make a sample code, check it out below

import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const [mounted, setMounted] = useState(false)

  if(!mounted){
    // Code for componentWillMount here
    // This code is called only one time before intial render
  }

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

  return (
    <div className="App">
      
    </div>
  );
}
  • As you mentioned you want to make an api call, it usually happen in componentDidmount and you can simply use useEffect hook with empty array as dependencies in functional component

import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const [mounted, setMounted] = useState(false)


  useEffect(() =>{
    // This is similar to componentDidMount
    // Call back-end api here
  },[])

  return (
    <div className="App">
      
    </div>
  );
}
Tony Nguyen
  • 3,298
  • 11
  • 19
  • 1
    And it's not like linter such a condition wouldn't let go because you can't do hooks conditionally? It's an antipattern according to the documentation from what I remember. – TheTanadu Aug 29 '21 at 08:25
8

Actually, I want to add more cases here, and I am going to make reusable custom hooks.

1.Care about extra dom render

It will not cause extra dom render

const useOptimizedComponentWillMount = callback => {
  const mounted = useRef(false)
  if (!mounted.current) callback()

  useEffect(() => {
    mounted.current = true
  }, []);
};

Note: You might want mounted && mounted.current in typescript

2. Don't care about extra dom render

this is exactly Tony answer

const useComponentWillMount = callback => {
  const [mounted, setMounted] = useState(false)
  if (!mounted) callback()

  useEffect(() => {
    setMounted(true)
  }, [])
};

Usage

const App = () => {
  useComponentWillMount(() => console.log("will mount"))
  return console.log("render-dom") || <div>Layout</div>
};
// will mount
// (2)render-dom
const App = () => {
  useOptimizedComponentWillMount(() => console.log("will mount"))
  return console.log("render-dom") || <div>Layout</div>
};
// will mount
// render-dom
amirhe
  • 2,186
  • 1
  • 13
  • 27