How does calling “setState” as a callback in a function, without any new state value, successfully update the state?

55
January 25, 2020, at 11:20 PM

I saw this code snippet recently, and am wondering how the state variable actually gets updated here. This is the authentication state observer used in firebase authentication to determine if a user is signed in (docs reference). Normally, this is how it functions:

const [userData, setUserData] = useState(null)
firebase.auth().onAuthStateChanged(user => {
  if (user) {
    // User is signed in.
    setUserData(user); // can now access properties of user
  }
});

However, this code updates userData in the exact same way by placing setUserData in place of the callback in the function:

const [userData, setUserData] = useState(null)
firebase.auth().onAuthStateChanged(setUserData);

Both of these functions set userData as the same object. How does this work, in the second snippet, where the state is updated by not using a tangible value to update the state?

Answer 1

The second call uses a function that is defined elsewhere as the callback, while the first uses a newly defined function.

See example below:

function log(data) { 
  console.log(data); 
} 
 
function someFunction(callback) { 
  setTimeout(()=>{ callback("my data")}, 1000); 
} 
 
 
someFunction( (data)=> console.log(data) ); // use new function 
someFunction( log ); // reuse a defined function

Answer 2

That's simply the way it works in javascript. Functions are a first class citizens which you can assign to variables and pass as an arguments. Here, setUserData is passed as a first argument of onAuthStateChanged. For a better understanding, consider something like this:

const [userData, setUserData] = useState(null)
const handleAuth = user => {
  if (user) {
    setUserData(user);
  }
}
firebase.auth().onAuthStateChanged(handleAuth);

Both setUserData and handleAuth expects user as a first argument, so both functions are ok to pass as a callback to onAuthStateChanged.

Answer 3

Both of the following way is same:

firebase.auth().onAuthStateChanged(user => setUserData(user))
// OR,
firebase.auth().onAuthStateChanged(setUserData)

So, when you use arrow function you explicitly set user as parameter to setUserData and when you use it as callback it implicitly sets user parameter to it.

READ ALSO
Reading images from remote link instead of the FileReader to perform image compression based on JIC

Reading images from remote link instead of the FileReader to perform image compression based on JIC

I am experimenting with JIC (Javascript Image Compressor by brunobar79 and am trying to visually compress images by using a slider directly on the pageI've been expanding on the demo provided and so far I'm able to upload a local image using the FileReader...

49
Vuejs - Vue App build as component for other project's vue router

Vuejs - Vue App build as component for other project's vue router

Im trying to build a vue app for other vue project's to be use as a component for the app vue routerHere is my simple project structure for start,

49
How to display multiple arrays of objects in Recharts?

How to display multiple arrays of objects in Recharts?

How can I display two arrays of objects in Recharts ?

43