简体   繁体   中英

How are different function signatures differentiated in setState function returned by `React.useState`?

I'm new to JavaScript and React.

I was reading from React's documentation https://reactjs.org/docs/hooks-reference.html#functional-updates

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

And was curious how different function signatures are being handled in setState (here setCount ) function returned by React.useState .

Since JavaScript is a dynamically typed language and therefore function overloading does not exist, my initial guess was that there's only a single function that simulates the behavior of function overloading, such as in this question Function overloading in Javascript - Best practices .

Or is this handled in some different way by React?

EDIT: I think this question could be also applied to the React.useState function itself https://reactjs.org/docs/hooks-reference.html#lazy-initial-state

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

my initial guess was that there's only a single function that simulates the behavior of function overloading

Yes, in javascript if you want a function to take a variety of different parameters, you write a single function and then write code that checks what was passed in. For example:

const example = (val) => {
  if (typeof val === 'function') {
    // do the function behavior
  } else {
    // do the other behavior
  }
}

EDIT: since you want to know the code that react specifically uses, here goes. In short, it does the same thing i just answered, but with more steps to get there.

The starting point for your expedition through the code is this file . This is the function you call when you call useState . However, all it does is turn around and ask "dispatcher" to do useState.

The "dispatcher" is a way to handle the fact that there are several different ways react can be used, and they sometimes need different implementations of hooks. For example, you might be rendering on the server, or on the dom, or on react native, or in a custom renderer.

Finding those dispatchers in react's codebase is going to be tricky. They're spread all over the place in different packages, since it's only those packages that need the specific implementations.

Additionally, when you find an implementation, it's going to have a lot of reuse of functions, since they do similar things. useState is just a special case of useReducer, so it's going to reuse useReducer as a way to implement useState.

All that to say that when you call setState , here is one example of the places the code could end up:

function basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {
  // $FlowFixMe: Flow doesn't like mixed types
  return typeof action === 'function' ? action(state) : action;
}

The action param is the value or function you passed into setState. If it's a function, it will call it and pass in the most recent state, then return whatever your function returns. If it's not a function, it will just return what you passed in. This return value then becomes the new state .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM