17

React Docs says:

How does React associate Hook calls with components?

React keeps track of the currently rendering component. Thanks to the Rules of Hooks, we know that Hooks are only called from React components (or custom Hooks — which are also only called from React components). 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.

First of all... what is this "memory cell"? Can we print it out ourselves to see its value?

Second, there is only one instance of the function (such as Counter() in the following example). So if we render <Counter /> twice into the DOM, once to <div id="root1"> and the second time to <div id="root2">, how does the function Counter() know which is which?

function Counter() {

    let [count, setCount] = React.useState(0);

    return (
        <div>
            <button onClick={() => setCount(count + 1)}> + </button>                    
            { count }
            <button onClick={() => setCount(count - 1)}> - </button> 
        </div>
    )
}
nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • You are essentially invoking the function `Counter` 2 times when rendering 2 instances of it. React assigns a unique key to a component. So the first thing is you have two instances of this component running. The next part is `useState` is local to a component's instance. So for each instance of a component you render they each have their own local state. This is similar in concept to a class component's state. – John Ruddell Feb 13 '20 at 05:12
  • @JohnRuddell every time new content is shown for this component, Counter() is called. It can be called 5000 times – nonopolarity Feb 13 '20 at 06:06
  • Not sure what the question is in that statement. When a component re-renders it will execute. `React.useState` is created once and then reused in subsequent renders. Think of it like how you would memoize something. – John Ruddell Feb 13 '20 at 07:10
  • I know how to use it. I just don't know how it can be implemented – nonopolarity Feb 13 '20 at 07:18
  • well i'd look at the source if I want to know more about how it works. you can see the definition of `useState` [here](https://github.com/facebook/react/blob/master/packages/react/src/ReactHooks.js#L78). and then the dispatcher is getting assigned in a few places like [here](https://github.com/facebook/react/blob/f7278034de5a289571f26666e6717c4df9f519ad/packages/react-reconciler/src/ReactFiberHooks.js#L399). if you notice the `memoizedState` i think that'll give you a clue :) – John Ruddell Feb 13 '20 at 07:48
  • Not sure this "React assigns a unique key to a component. So the first thing is you have two instances of this component running" is true as the return mount only one component with 2 button that call 2 setCounter, so there are 2 Counters and not 2 components – Carmine Tambascia Feb 13 '22 at 20:09
  • @nonopolarity have you then found or implemented those JS objects? For me memory cell seems refer to either virtual memory that map the actual hardware, but most probably are "virtual" so also objects – Carmine Tambascia Feb 13 '22 at 20:11

1 Answers1

5

Let's say you have two of your counters inside a parent container JSX:

<div>
  <Counter/>
  <Counter/>
</div>

This is how React can 'know which is which' (extremely simplified):

const componentStates = [ { value: 13 }, { value: 27 } ]; //"memory cells"
let context;

// the parent container JSX will be transformed/executed in this way:
function render() {
    context = componentStates[0];
    Counter();

    context = componentStates[1];
    Counter();
}

function useState() {
    return [ context.value, updateFunction ];
}

function updateFunction(newValue) {
    context.value = newValue;
    render();
}

A key concept to understand this is, that React.useState is not a pure function, it relies on the rendering context.

Knight Industries
  • 1,325
  • 10
  • 20