reactjsreact-hooks

useState vs. useEffect - setting initial value


I have two basic questions about React:

  1. In order to assign an initial empty value to a piece of state (let's say player) in a functional component, are the following two approaches the same or are they different in some way?

Approach A:

const [player, setPlayer] = useState({})

Approach B:

useEffect(() => {
    setPlayer({})
}, []);
  1. When I browse to a player, the page is eventually updated with values coming from the global store so I need to avoid showing the values of the previous player while the current one is still loading. What is the best way to go about this?

Please let me know if you need more background information in order to help.
Thank you in advance!


Solution

  • When assigning initial value directly in useState(initialData) you are making that state available in the very first render.

    On the other hand, if you are setting the initial value in a useEffect hook, it will be set on mount, but after the very first render.

    useEffect(() => {
        setPlayer(initialData)
    }, [])
    

    If the state variable is important also for the first render, then you should use the first approach. It is also shorter to write and makes more sense.

    enter image description here

    Example:

    if you open your devtools when running this example, the debugger will pause inside the useEffect and you will see a red circle. Only then the state gets updated which causes the component to re-render.

    If you were to edit the code and write useState(initialData), you would see the first render did include the correct state when the (when debugger pauses code execution).

    const {useState, useEffect, useLayoutEffect} = React
    
    const App = ({initialData}) => {
      const [value, setValue] = useState('🔴') 
    
      useEffect(() => {
        // at this point, the component has already been rendered
        debugger; 
    
        // updating the state below will cause a re-render
        setValue(initialData)
      }, [])
    
      return value
    }
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<App initialData={'🟢'} />);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <div id='root'></div>