4

the React Hooks useState can attach local state to stateless functional component, for instance

const [name, setName] = useState('tom')
const [age, setAge] = useState(25)

I am wondering how the local state object tree looks like after executing the two line above? Rules of Hooks says something about how state is handled

React relies on the order in which Hooks are called

Or the local state is not object tree at all, just an array?

Thanks in advance!

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
Sam D.
  • 265
  • 2
  • 10

1 Answers1

13

Hooks internally are implemented as a queue with each hook being represented by a node having the reference to the next one.

From the documentation:

There is an internal list of “memory cells” associated with each component. They’re just JavaScript objects where we can put some data. When you call a Hook like useState(), it reads the current cell (or initializes it during the first render), and then moves the pointer to the next one. This is how multiple useState() calls each get independent local state.

The architecture would be similar to

{
  memoizedState: 'A',
  next: {
    memoizedState: 'B',
    next: {
      memoizedState: 'C',
      next: null
    }
  }
}

The schema of a single hook is as below. It can be found in the implementation

function createHook(): Hook {
  return {
    memoizedState: null,

    baseState: null,
    queue: null,
    baseUpdate: null,

    next: null,
  };
}

The key properties that let hooks behave the way they are are memoizedState and next.

Before each and every function Component invocation, prepareHooks() is gonna be called, where the current fiber and its first hook node in the hooks queue are gonna be stored in global variables. This way, any time we call a hook function (useXXX()) it would know in which context to run.

After the update finishHooks() will be called, where a reference for the first node in the hooks queue will be stored on the rendered fiber in the memoizedState property

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • It there a reason why hooks do not allow a name parameter to be passed to solve this problem? e.g. `useState("tom", "state_1")` and fall back to order when the second argument is missing? There might be even the constraint that all hooks should be called on the first render or a reasonable behaviour for late calls? Or is it meant to enforce that all hooks be called at every render? (in the sense that hook-names could solve the ordering problem but it is necessary that all hooks are called at every render) – afiori Aug 31 '20 at 13:07