Получи случайную криптовалюту за регистрацию!

Почему нельзя вызывать хуки по условию Например, компонент по | Заметки про React

Почему нельзя вызывать хуки по условию

Например, компонент по определенному условию вернул null. Это невалидный код на React. Но почему так делать нельзя?

const ConditionalComponent = (props) => {
if (!props.visible) return null;

const [value, setValue] = useState();
}


В первую очередь стоит помнить, что babel компилирует код JSX в обычные функции createElement:

const MyComponent = () => {
return
Hello world

}

// babel компилирует в
const MyComponent = () => {
return React.createElement("div", null, "Hello world");
};

React рендерит компоненты, вызывает createElement, создает Virtual DOM и выводит пользователю в браузер отрендеренные элементы. Рендер – это просто вызов функции функционального компонента. Функциональный компонент вызывается, возвращается вызов createElement, React сравнивает текущее и новое дерево VDOM и коммитит изменения в DOM.

Важно понимать, что функциональный компонент это функция, которую вызывает React. Это создает проблему: как сохранить данные в стейте при вызовах функции (рендере). Например, следующий код при каждом вызове будет писать в консоль “1”:

const Test = () => {
let a = 1;
console.log(a);
a++;
}

Test(); // 1
Test(); // 1
Test(); // 1


Для того чтобы сохранять состояние стейта между рендерами компонента, React сохраняет состояние во внешнем объекте по ID хука, примерно так:

const state = [];

// Уникальный ID хука, счетчик
let idx = 0;

function useState(init) {
state[idx] = state[idx] ?? { val: init };

return [
state[idx].val,
data => state[idx].val = data
]
}

function Test() {
const [name, setName] = useState('React');
}

Вот почему мы не можем условно отображать хуки: они отслеживаются на основе порядка вызовов, используя в качестве ID счетчик.

Более подробно про хуки написано в блоке Дэна Абрамова: https://overreacted.io/why-do-hooks-rely-on-call-order/