Комментарии 21
Эх, из названия статьи ожидал что будет о внутреннем устройстве хуков, т.е. как вроде как чистая функция может сохранять некое состояние между вызовами и другие подробности реализации. А тут просто очередной разбор базовых хуков для новичков.
Реакт компоненты не являются чистыми функциями, вас обманули.
По-подробней пожалуйста. Если функция использует хук, да, она хранит состояние за пределами функции, (не помню как этот менеджер данных называется в реакте), но буду признателен за развёрнутый ответ: «а что кроме этого».
Кроме этого есть состояние в замыканиях и контекстах.
Абрамов писал, что для него тут важнее идемпотентность функций, нежели чистота. Если наличие скрытых состояний не мешает функции возвращать одно и то же, то какая разница?
Как она можуть возвращать одно и то же, если это зависит от стейта и контекста, а не только от аргументов?
Эти компоненты правильно называть не функциональными, а процедурными.
https://overreacted.io/react-as-a-ui-runtime/#purity. Идемпотентность это свойство отдельной операции, а не системы. В том же смысле, что SELECT в SQL или GET в ReST должны быть идемпотентными, хотя содержимое базы может изменяться другими операциями, что повлияет на результат. Чистота функций в ФП связана с сылочной прозрачностью, которая в свою очередь тоже связана с идемпотентностью, но не только.
Функциональный компонент в React сам не должен менять стейт или контекст в процессе исполнения. В dev режиме это даже проверяется, запуская рендер дважды. Контекст фактически является для неё данными - indirect input.
ребят, я джун, пишу на классовых компонентах. на хуки не тянет, по одной простой причине - не вижу возможности менять однотипные переменные. скажем, есть форма с тремя текстовыми инпутами, в классовом пишем что-то типа
change = (name, val) => {
this.setState({[name]:val})
}
и будь у нас хоть 100 инпутов с разными переменными, используется одна функция. что в таком случае делается с хуками?
const component = () => {
const [state, setState] = useState({});
const change = useCallback((name, value) => {
setState({...state, [name]: value});
});
// ...
};
взять form-manager типо react-hook-form, чтобы клиент не умирал от ререндера формы
Обратите внимание, что в качестве аргумента в createContext мы передали строку (“without context”). Его значение попадет в переменную context в том случае, если вы вдруг забудете создать обертку MyContext.Provider, то есть он поможет не допустить ошибку из-за невнимательности.
Вот лучше бы они сделали выброс исключения, если нет провайдера. Тогда в TS можно было бы без всяких приведений типов (или без дурацких заглушек) делать просто createContext<MyType>()
Вот лучше бы они сделали выброс исключения
Я бы за такое спасибо не сказал. Бывают ситуации когда контекст несёт вспомогательную роль. Два хука делать?
Нет, зачем 2? Просто сделать в createContext необязательное дефолтное значение, и только если оно не указано и нет провайдера, вываливать эксепшн.
Сейчас, если контекст не вспомогательный и провайдер точно нужен, то приходится либо createContext<MyType | null>(null), что неудобно в использовании, либо createContext<MyType>(null as unknown as MyType), тоже не очень красиво и не "ts-way", либо воткнуть туда бессмысленную заглушку.
<button onClick={() => valueChange(value + 1)}>
увеличить значение на 1
</button>
Антипаттерн, дальше лень читать
https://overreacted.io/react-as-a-ui-runtime/#batching
рекомендую ознакомиться(можно обобщить на весь блог Дэна Абрамова)
А в чем заключается антипаттерн? Если в незавернутом в usecallback инлайнере, то в данном случае я б сказал что антипаттерн как раз наоборот - оборачивать все подряд направо и налево в мемоизаторы различных мастей.
Про useRef акцент неправильный. Этот паттерн в первую очередь был нужен для хранения и передачи ссылок на DOM-элементы. А сейчас предполагается универсальным и сохраняет случайные данные в инстансе без его обновления.
А как же useImperativeHandle
? Считаю, очень заслуживает упоминания наряду с useRef
, позволяет вызывать методы дочернего функционального
компонента.
React Hooks простыми словами