Ryong9rrr
Ryong9rrr

Reputation: 3

Why does the code(funtional) for the hook keep rendering? (compared to Class)

I just started react...

This code is simply rendered after 3 seconds using Boolean value.

But the code below keeps rendering.. rendering.. rendering... almost every three seconds.

import React, { useState } from "react";

const App = () => {
  const [isLoading, setIsLoading] = useState(true);

  setTimeout(() => {
    setIsLoading(!isLoading);
  }, 3000);

  return <h1>{isLoading ? "Loading" : "we are ready"}</h1>;
};

export default App;


But this code works well. What is the reason?

import React, { Component } from "react";

class App extends React.Component {
  state = {
    isLoading: true,
  };

  componentDidMount() {
    setTimeout(() => {
      this.setState({
        isLoading: false,
      });
    }, 3000);
  }

  render() {
    return <div>{this.state.isLoading ? "Loading..." : "we are ready"}</div>;
  }
}

export default App;

Upvotes: 0

Views: 162

Answers (3)

DustInComp
DustInComp

Reputation: 2666

A function component is called on every render. That means the timeout is created on every re-render after a state change as well, when implemented like in your first example. To use the component lifecycle, you should use the useEffect hook: https://reactjs.org/docs/hooks-reference.html#useeffect

import React, { useEffect, useState } from "react";

const App = () => {
  const [isLoading, setIsLoading] = useState(true);

  // Set a timeout ONCE when the component is rendered for the first time
  // The second argument [] signifies that nothing will trigger the effect during re-renders
  useEffect(() => {
    setTimeout(() => {
      setIsLoading(false);
    }, 3000);
  }, [])

  return <h1>{isLoading ? "Loading" : "we are ready"}</h1>;
};

export default App;

Upvotes: 4

Konstantin Samarin
Konstantin Samarin

Reputation: 867

Answer from MubtadaNaqvi will unfortunately result in infinite loop. You should apply useEffect properly:

  useEffect(() => {
    setTimeout(() => {
      setIsLoading(isLoading => !isLoading);
    }, 1000);
  }, [])

Upvotes: 0

MubtadaNaqvi
MubtadaNaqvi

Reputation: 197

Because you are initializing isLoading with true value in the state. and whenever the state is changed functional components rerenders, and it doesn't happen in Class-based component as you have used the component life cycle method. You should use "useEffect" in the functional component.

  useEffect(() => {
    setTimeout(() => {
      setIsLoading(!isLoading);
    }, 3000);
  });

you can read about it here https://reactjs.org/docs/hooks-effect.html

Upvotes: 0

Related Questions