skip to Main Content

I am new to React and have a hard time understanding why when I call useEffect after I just set the new state on a variable, the new value is undefined. Can someone also explain why the second UseEffect hook is called twice. Is it because it’s called on initial mount, and then called when it finally changes state from the first useEffect? How can I get it to fire only once val has a defined value that was set in the first useEffect?

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

export function App(props) {
  const [val, setVal] = useState();
  useEffect(() => {
    setVal("hello");
  },[]);
  useEffect(() => {
    console.log("value: ", val);
  }, [val])

  return (
    <div className='App'>
    </div>
  );
}

2

Answers


  1. You do not need more than one useEffect. In this instance one would work:

    import React, {useState, useEffect} from 'react'
    
    export default function App() {
      const [val, setVal] = useState('');
    
      useEffect(() => {
        setVal("hello");
        console.log("value: ", val);
      }, [val])
    
      return (
        <div className="App">
          {val}
        </div>
      );
    }
    

    the useEffect you’re showing can change whenever the state is changed an example with updating state from an onClick:

    import React, {useState, useEffect} from 'react'
    
    export default function App() {
      const [val, setVal] = useState('');
    
      useEffect(() => {
        if (val === '') setVal("hello");
      }, [val])
    
      return (
        <div className="App">
          <button onClick={() => setVal('Is it Friday yet?')}>
            Click me
          </button>
    
          <div>{val}</div>
        </div>
      );
    }
    ``
    
    Login or Signup to reply.
  2. The code is working exactly as I’d expect it to.

    On (or more specifically, immediately after) the first render, both effects execute. Which:

    • queues a state update and
    • logs undefined to the console

    Then when state is updated, the component re-renders. This re-render has a new state value for val, which triggers the second useEffect to execute. Which:

    • logs "hello" to the console

    How can I get it to fire only once val has a defined value that was set in the first useEffect?

    If you want something to happen conditionally, you’d use an if statement. For example:

    useEffect(() => {
      if (val) {
        console.log("value: ", val);
      }
    }, [val])
    

    This will only log val to the console if it has a "truthy" value.

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