Как стать автором
Обновить
4
0
Алексей Мартинкевич @LEXA_JA

JS Developer

Отправить сообщение

В nodejs окружении нету document, т. к. это часть браузерного API. Мы пишем тесты на jest, и там используется https://github.com/jsdom/jsdom. Не подскажу как насторить mocha, но можно попробовать подключить jsdom. Eсли не хочется тянуть либу то можно замокать, или может запускать тесты в браузере.

Аннотации работают, но нужно что-то настроить. В vscode это работает через typescript. Если не ошибаюсь нужен jsconfig.json. Несколько лет назад я так работал на проекте с JS + JSDoc, и всё это заводил. Как по мне, с typescript это не сравнить. Минимальный функционал IDE это даёт, но никаких надёжных рефакторингов и гарантий по факту нет.
Сомневаюсь что typescript станет web стандартом. Скорее уже WASM допилят и туда можно будет компилировать другие языки.

Это эксперементальное API, в официальной документации не описано. Соотносить селекторы на уровне того как в статье — для свойств объекта первого уровня — не проблема. Каждое свойство получает маску по типу 0b1 << номер_свойства. И тогда селектор это селектор_свойста_1 | ... | селектор_свойства_n. Как-то соотносить это автоматически наверное можно, но нужно использовать свой API. Например useContextSelector(context, ["foo", "bar"]). Или может какой-нибудь babel плагин, что-бы посчитать заранее.
Это может работать когда у нас есть несколько независимых свойств в контексте, но не для чего-то по типу redux.


Что говорят разработчики реакта по этому поводу:
Приёмы для оптимизации
Обсуждение

Я так думаю это потому-что можно сделать что-то похожее очень просто. Конечно делать так не стоит, но руки у людей чешутся.

В случае создания своей обертки над React.createContext, нет нужды лезть в кишки реакта и что-то делать с _currentValue. Можно сделать обёртку над провайдером, которая будет хранить не значение контекста, а что-то вроде observable:


function CustomProvider({ value, children }) {
  // observableValue создается едоножды и соответственно не вызывает перерисовок
  const [observableValue] = useState(() => new ObservableValue());

  useEffect(() => {
    // засовываем туда наше значение из контекста
    // под капотом `setValue` должен посчитать что изменилось и оповестить соответствующих слушателей
    observableValue.setValue(value);
  }, [value]);

  return (
    <Context.Provider value={observableValue}>{children}</Context.Provider>
  );
}

И в кастомной обертке над React.useContext:


function useMyCustomContext(context) {
  const observableValue = useContext(context);

  const [, update] = useState(0);

  // вместо boolean лучше использовать число
  const forceUpdate = useCallback(() => {
    update(prev => prev + 1);
  }, [update])

  useEffect(() => {
      // детали я оставил за кадром
      // тут мы подписываемся только на интересующие нас поля по какому-то правилу `rule`
      // это может быть списко полей объекта или функция, или что-то ещё.
      // например если мы хотим использовать Proxy как в статье, то
      // `observableValue.getValue()` может вернуть Proxy, который будет создавать `rule`
      observableValue.listen(rule, () => forceUpdate()))
  }, [])

  return observableValue.getValue();
}

При это в имплементации может быть любая существующая библиотека для реактивности, например rxjs или mobx.


опора на внутреннюю реализацию реакта, которая в будущем может поменяться
все проблемы Monkey patchинга
нельзя использовать в классовых компонентах — только вместо useMyCustomContext нужна похожая обертка для классов
нельзя использовать один контекст в нескольких провайдерах

А ещё я бы рекомендовал посмотреть на второй аргумент в useContext и createContext:
React Context: a Hidden Power

Ещё можно использовать деструктуризацию объекта по отношению к массиву:


const { 3: x, 4: y } = [1, 2, 3, 4, 5];

console.log(x, y); // 4, 5

Если использовать webpack-dev-middleware то (вроде бы) можно сделать это без перезапуска процесса, а просто заставить сработать watcher, что будет немного быстрее и всё in-memory состояние сохраниться. Но если всё уже работет, то смысла переделывать наверное уже нет.

У вебпака есть програмный API, и у webpack-dev-server тоже
соответственно можно поднять свой express и и приделать API для перезапуска. В теории должно быть можно так сделать, но знаю насколько просто.
Мы использовали такое когда в там ещё не было встроенного прокси.

Да, я согласен, это довольно слабый аргумент, по сравнению с остальными, но я так понимаю, это основано на отзывах. Хуки заменили сложности с this на замыкания и ссылочное равенство. Ещё часть про "Classes confuse both people and machines" относится к проблемам с минификаторами и typescipt'ом. Поля классов не могут быть минифицированы без проблем и вывод типов хромал, особенно с HOC.

Хуки были созданы для решения проблемы переиспользования логики привязанной к жизненному циклу компонента. До этого использовали HOC и Render props, а ещё раньше — миксины. Проблема HOC — общее пространство имен пропсов, а render props засоряют дерево компонентов и всё это не удобно композировать.


Хуки позволяют удобно управлять тем, куда передавать и откуда брать пропсы. Например можно с легкостью подключить один хук несколько раз с разными пропсами, можно передавать выход из одного хука в другой и т.д.


У хуков конечно есть и свои проблемы, но они решили определенный класс проблем.


Официальная мотивация

Потому что браузерам не очень прикольно поддерживать множество различных режимов работы JS. В strict mode зашли изменения, в том числе мешающие оптимизациям и необходимые для ES6+.

Относительный url будет относителен странице (html), а не некоторому js-модулю, в котором относительный импорт на другой js-модуль.

es6 модули разрешают пути относительно скрипта, из которого был сделан импорт


// index.html

<script type="module" src="./src/main.js"></script>

// src/main.js
import "./some/module.js"

Если сервер на http://example.com, то запросы будут:
http://example.com/src/main.js
http://example.com/src/some/module.js

Несколько элементов в одном общем контейнере?

Prettier переносит строки в зависимости от длинны. Иногда увеличение\уменьние длины строки на пару символов попадает на брейкпоинт и происходит переформатирование.

Для тестов: EQAYFlAqxFYuWluL9qWMJIEPxVsoaVXAxIWWgAzwDeWWrdE1
Invoice на 3.50: ton://transfer/EQAYFlAqxFYuWluL9qWMJIEPxVsoaVXAxIWWgAzwDeWWrdE1?amount=3500000000

Тольуко у композиции функций немного другая сигнатура:


GHCi>:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

Ну у миксинов были проблемы с конфликтами имен и неявными зависимостями между миксинами, поэтому от них отказались в пользу HOC'ов. Еще из плюсов для хуков это возможность подключить один хук несколько раз. Вообще говоря классы в React тоже имеют мало общего с ООП, а о наследовании компонентов вообще упоминать не принято.
Не буду спорить с тем, что принципиально возможно сделать нормальный API и для классов, но в текущей реализации хуки удобнее классов.

Одно из ключевых преимуществ хуков перед классами это возможность создавать переиспользуемые и комбинируемые куски логики. Хуки являются однозначно более удобным решением чем Render Props, и нередко более удобны, чем HOC'и. Именно возможность удобно создавать кастомные хуки является самой мощной фичей хуков. Если честно, я совсем не против API классов, но там была проблемы именно с выделением кусков логики и привязки к конкретному компоненту. Я не совсем представляю как можно решить именно эту проблему через API классов.

Этот оператор не имеет никакого отношения к приведению к boolean. Этот оператор убирает null из типа.

Информация

В рейтинге
Не участвует
Откуда
Гродно, Гродненская обл., Беларусь
Дата рождения
Зарегистрирован
Активность