Обложка канала

Заметки про React

Короткие и полезные заметки про React

Заметки про React

4 года назад
Открыть в
Почему нельзя вызывать хуки по условию Например, компонент по определенному условию вернул null. Это невалидный код на React. Но почему так делать нельзя?
const ConditionalComponent = (props) => {
 if (!props.visible) return null;

 const [value, setValue] = useState();
}
В первую очередь стоит помнить, что babel компилирует код JSX в обычные функции createElement:
const MyComponent = () => {
 return <div>Hello world</div>
}

// 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 счетчик. Более подробно про хуки написано в блоке Дэна Абрамова: overreacted.io/why-do-…ll-order
Why Do React Hooks Rely on Call Order?

Lessons learned from mixins, render props, HOCs, and classes.

overreacted.io