What can I use in functional components to have same behavior as componentDidMount?

My UI was working fine until it was using a class component. Now I am refactoring it to a functional component.

I have to load my UI based on the data I receive from an API handler. My UI will reflect the state of the camera which is present inside a room. Every time the camera is turned on or off from the room, I should receive the new state from the API apiToGetCameraState.

I want the console.log present inside the registerVideoStateUpdateHandlerWrapper to print both on UI load for the first time and also to load every time the video state is changed in the room. However, it doesn’t work when the UI is loaded for the first time.

This is how my component looks like:

const Home: React.FunctionComponent<{}> = React.memo(() => {
  const  = React.useState(true);

  const registerVideoStateUpdateHandlerWrapper = React.useCallback(() => {
    apiToGetCameraState(
      (videoState: boolean) => {
        // this log does not show up when the UI is loaded for the first time
        console.log(
          `Video value before updating the state: ${video} and new state is: ${videoState} `
        );
        setToggleVideo(videoState);
      }
    );
  }, );

  React.useEffect(() => {
    //this is getting called when the app loads
    alert(`Inside use effect for Home component`);
    registerVideoStateUpdateHandlerWrapper ();
  }, [registerVideoStateUpdateHandlerWrapper ]);

  return (
      <Grid>
        <Camera
          isVideoOn={video}
        />
      </Grid>
  );
});

This was working fine when my code was in class component. This is how the class component looked like.

class Home extends Component {
    
    registerVideoStateUpdateHandlerWrapper = () => {
        apiToGetCameraState((videoState) => {
            console.log(`ToggleVideo value before updating the state: ${this.state.toggleCamera} and new state is: ${videoState}`);
            this.setStateWrapper(videoState.toString());
        })
    }
    setStateWrapper = (toggleCameraUpdated) => {
        console.log("Inside setStateWrapper with toggleCameraUpdated:" + toggleCameraUpdated);
        this.setState({
            toggleCamera: (toggleCameraUpdated === "true" ) ? "on" : "off",
        });
    }
   
    constructor(props) {
        super(props);
        this.state = {
            toggleCamera: false,
        };
    }
    componentDidMount() {
        console.log(`Inside componentDidMount with toggleCamera: ${this.state.toggleCamera}`)
        this.registerVideoStateUpdateHandlerWrapper ();   
    }
    render() {
      return (
        <div>
          <Grid>
            <Camera isVideoOn={this.state.toggleCamera} />
          </Grid>
     );
  }
}

What all did I try?

  1. I tried removing the useCallback in the registerVideoStateUpdateHandlerWrapper function and also the dependency array from React.useEffect and registerVideoStateUpdateHandlerWrapper. It behaved the same
  2. I tried updating the React.useEffect to have the code of registerVideoStateUpdateHandlerWrapper in it but still no success.

8 thoughts on “What can I use in functional components to have same behavior as componentDidMount?”

  1. Move registerVideoStateUpdateHandlerWrapper() inside the useEffect() callback like this:

    const Home = () => {
      const [video, setVideo] = useState(false);
    
      useEffect(() => {
        const registerVideoStateUpdateHandlerWrapper = () => {
          apiToGetCameraState((videoState) => {
            setVideo(videoState);
          });
        };
    
        registerVideoStateUpdateHandlerWrapper();
      }, []);
    
      return (
        <div>
          <Grid>
            <Camera isVideoOn={video} />
          </Grid>
        </div>
      );
    };
    
    Reply

Leave a Comment