skip to Main Content

As already specified in the title, useEffect renders the other components even if I pass the empty array.

I’m a girl who is just starting to learn react; i can’t figure out why if i pass empty array or ‘name’ in dependency array the action is still the same, but it shouldn’t be.

This is my code:

App.js

export default function App() {  
    return (
      <>       
        {/* First render */}
        <Greet name="Eric" />   

        {/* Second render, name prop changes */}
        <Greet name="Stan" />   

        {/* Third render, name prop changes */}
        <Greet name="Butters" /> 
      </>
    )
  }

Greet.js

import { useEffect } from "react";

export default function Greet({ name }) {

    const message = `Hello, ${name}!`;  

    useEffect(() => {
        console.log(`Greetings to ${name}`); // Side-effect!
    }, []);

    return (
        <div>{message}</div>
    )
}

From what I understand, with the empty array it only needs to render the first component

2

Answers


  1. To fix this, you need to make sure that the name prop is not changing on each render. You can do this by using the useState hook to store the name prop. This way, the name prop will only change when the user changes it, and the useEffect hook will only run when the name prop changes.

    import React, { useState } from "react";
    
    function App() {
      const [name, setName] = useState("Eric");
    
      return (
        <>
          <Greet name={name} />
          <Greet name={name} />
          <Greet name={name} />
        </>
      );
    }
    
    function Greet({ name }) {
      const message = `Hello, ${name}!`;
    
      useEffect(() => {
        console.log(`Greetings to ${name}`); // Side-effect!
      }, []);
    
      return (
        <div>{message}</div>
      );
    }
    
    export default App;
    

    Sure, I can give you an example of how to change your code so that the useEffect hook only renders the first component.

    In your original code, you are passing an empty array to the dependency array of the useEffect hook. This tells React that the useEffect hook should only run once, after the initial render of the component. However, the name prop is changing on each render, which is a dependency of the useEffect hook. This means that the useEffect hook will be called on each render, even though you are passing an empty array to the dependency array.

    import React, { useEffect } from "react";
    
    const Greet = ({ name }) => {
      const message = `Hello, ${name}!`;
    
      useEffect(() => {
        console.log(`Greetings to ${name}`); // Side-effect!
      }, [name]);
    
      return (
        <div>{message}</div>
      );
    };
    
    export default Greet;
    
    Login or Signup to reply.
  2. You need to understand 3 concepts here.

    First is reusable components. When you write something like this in App

    <Greet name="Eric" />   
    <Greet name="Stan" />   
    <Greet name="Butters" /> 
    

    It will be similar to this in html

    <div>Eric</div>
    <div>Stan</div>
    <div>Butters</div>
    

    So, in the App component you call the Greet 3 times. It created 3 instances of Greet component

    Secondly is useEffect,
    When you provide an empty dependency array [] as the second argument to useEffect, it means that the effect will only run once, after the initial render. It won’t run again when the component re-renders.

    In your case, you have 3 instances of Greet component inside App component, it run 1 time in 3 instances, so you see 3 console.log display.

    Thirdly is how React re-render when something change. Basically, React need something to notify it that the data has changed, and it need to re-render the component accordingly. One simple way is use useState for the data.

    So the example will be something like

    import React, { useState } from "react";
    
    function App() {
      const [name, setName] = useState("Eric");
    
      return (
        <>
          <Greet name={name} />
          <button onClick={() => setName('Stan')}>Change to Stan</button>
          <button onClick={() => setName('Butters')}>Change to Butters</button>
        </>
      );
    }
    
    function Greet({ name }) {
      const message = `Hello, ${name}!`;
    
      useEffect(() => {
        console.log(`1st name ${name}`); // Side-effect!
      }, []);
    
      useEffect(() => {
        console.log(`name changed ${name}`)
      }, [name])
    
      return (
        <div>{message}</div>
      );
    }
    
    export default App;
    

    Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search