Skip to content

20.2 useState

Как работает useState

Сначала стартует основная функция в которую передают компонент (по сути js функцию)

Создается объект saved с функцией и данными

Далее вызывается функция fn

При вызове внутри неё всё ещё будет доступ к componentFn и saved, поскольку они были в области видимости при создании функции fn.

connect.now: хранит текущий контекст выполнения компонента, что позволяет использовать глобальные переменные для отслеживания состояния между вызовами.

И далее вызывается сам компонент

    function connect (componentFn) {
        const saved = {
            fn () {
                connect.now = Object.assign(saved, { context: this, args: arguments, slot: 0 });

                const returnValue = componentFn.apply(this, arguments);

                delete connect.now;

                return returnValue;
            },
            data: []
        };

        return saved.fn;
    }
    function Example() {
      // Declare a new state variable, which we'll call "count"
      const [count1, setCount1] = useState(0);
      const [count2, setCount2] = useState(0);

      document.body.innerHTML = `
        <div>
          <p>You clicked ${count1} times</p>
          <p>You clicked ${count2} times</p>
          <button id="bt1">Click me1</button>
          <button id="bt2">Click me2</button>
        </div>
      `;

      document.getElementById('bt1').onclick = () => setCount1(count1 + 1);
      document.getElementById('bt2').onclick = () => setCount2(count2 + 1);
    }

Вызывается функция с значением по умолчанию

Объект saved восстанавливается из глобальной переменной

Значение слота указывает на то какой раз вызывается useState внутри этого компонента

Создается функция setValue, которая будет вызываться при изменении состояния

Когда она будет вызвана у нее будет доступ к saved и slot, она изменит значение и дальше вызовет функцию fn которая заного перерендерит компонент

    function useState (value) {
        const saved = connect.now;
        const { slot } = Object(saved);

        if (saved) {
            ++saved.slot;

            value = slot in saved.data
                ? saved.data[slot]
            : saved.data[slot] = value;
        }

        return [ value, setValue ];

        function setValue (newValue) {
            if (saved) {
                saved.data[slot] = newValue;

                saved.fn.apply(saved.context, saved.args);
            }
        }
    }

Вызов основной функции

    connect(Example)();

Info

1
2
Если не передавать this то все так же работает в моем примере, скорее всего 
это нужно когда используются вложенные компоненты и т.п.