На React Conf 2018 команда React представилаКрючки предложение.
Если вы хотите узнать, что такое хуки и какие проблемы они решают, ознакомьтесь снаши лекции(представлять),Понимание хуков React(распространенное недоразумение).
Сначала вам могут не понравиться крючки:
Они как музыкальное произведение, в которое влюбляешься лишь после того, как прослушаешь его несколько раз:
Читая документацию, не пропуститеСамая важная часть- Создайте свои собственные крючки! Слишком много людей настолько одержимы нашей точкой зрения (высокая стоимость обучения в классе), что упускают из виду более важный аспект крючков.functional mixins
, который позволяет вам создавать и создавать свои собственные хуки.
HooksВдохновленный некоторыми существующими технологиями, но я не знал об этом, пока Себастьян не поделился своими мыслями с командой. К сожалению, связь между этими API и тем, что используется в настоящее время, легко упускается из виду.С помощью этой статьи я надеюсь помочь большему количеству людей понять наиболее спорные моменты предложения Hooks.
Следующая часть требует от вас знания Hook API.useState
и как писать собственные хуки. Если вы все еще не понимаете, вы можете взглянуть на предыдущую ссылку.
(Отказ от ответственности: мнения в этой статье являются личными и не относятся к команде React. Тема большая и сложная, и в ней могут быть неправильные мнения.)
Сначала вы можете быть шокированы, когда узнаете, что хуки полагаются на фиксированный порядок при повторном рендеринге, вотиллюстрировать.
Решение, очевидно, спорное, поэтому любойпротив нашего предложения. Мы опубликуем это предложение в нужный момент, когда почувствуем, что документация и лекции описывают его достаточно хорошо.
Если вы следуете некоторым пунктам об API хуков, я предлагаю вам прочитать более 1000 комментариев Себастьяна RFC.Ответить всем,Достаточно ясно, но настолько информативно, что я мог бы превратить каждый абзац в комментариях в свой собственный пост в блоге. (На самом деле у менясделалоднажды! )
Есть один конкретный раздел, на котором я хочу сосредоточиться сегодня. Как вы помните, каждый хук может использоваться в компоненте несколько раз, например, мы можем использоватьuseState
утверждениенесколько состояний:
function Form() {
const [name, setName] = useState('Mary'); // State variable 1
const [surname, setSurname] = useState('Poppins'); // State variable 2
const [width, setWidth] = useState(window.innerWidth); // State variable 3
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
});
function handleNameChange(e) {
setName(e.target.value);
}
function handleSurnameChange(e) {
setSurname(e.target.value);
}
return (
<>
<input value={name} onChange={handleNameChange} />
<input value={surname} onChange={handleSurnameChange} />
<p>Hello, {name} {surname}</p>
<p>Window width: {width}</p>
</>
);
}
Обратите внимание, что мы используем синтаксис деструктурирования массива для имениuseState()
Возвращаемые переменные состояния, но эти переменные не будут привязаны к компоненту React. Вместо этого в этом примереРеагировать будетname
Рассматривается как «первая переменная состояния»,surname
Взять «вторую переменную состояния», чтобы нажать. Они используются при повторном рендерингепоследовательный вызовдля обеспечения правильной идентификации.эта статьяПричина подробно описана.
На первый взгляд полагаться на последовательные вызовы просточувствовать проблему, интуиция — полезный сигнал, но иногда она может ввести нас в заблуждение, особенно если мы не полностью разобрались с загадкой.В этой статье я упомяну несколько схем, которые часто предлагают модифицировать Хуки, и их проблемы.
Этот пост не будет исчерпывающим, как вы можете видеть, мы рассмотрели от дюжины до сотен различных альтернатив, и мырассмотреть возможностьЗамените API компонента.
Вести такой блог сложно, потому что, даже если вы расскажете о сотне вариантов, кто-то заставит одного сказать: «Ха-ха, ты не подумал об этом».это"!
На практике будет много повторения проблем, упомянутых разными альтернативами, я не буду их перечислять.все建议的API(这需要花费数月时间),而是通过几个具体示例展示最常见的问题,更多的问题就考验读者举一反三的能力了。 🧐
Это не значит, что крючки идеальны., но как только вы поймете подводные камни других решений, вы можете обнаружить, что дизайн Hooks имеет смысл.
Дефект №1: невозможно извлечь пользовательские хуки
Удивительно, но большинство альтернатив вообще не упоминают об этом.custom hooks. Вероятно, потому, что мы не уделили достаточного внимания пользовательским хукам в «мотивационных» документах, но это трудно сделать, пока вы не поймете основы хуков. Как проблема курицы и яйца, но в основном в центре внимания предложения находятся нестандартные крючки.
Например: альтернативой является ограничение количества обращений к компонентуuseState()
Вы можете положить в состояние, где объект, который также может быть совместимым с классом, не лучше?
function Form() {
const [state, setState] = useState({
name: 'Mary',
surname: 'Poppins',
width: window.innerWidth,
});
// ...
}
Чтобы было понятно, хуки разрешено писать в этом стиле, вам не нужно разбивать состояние на кучу переменных состояния (см. ответ на вопроспредложение).
но поддерживает несколько вызововuseState()
Суть в том, что вы можете извлечь некоторую логику состояния (состояние + эффекты) из компонентов в пользовательские хуки, при этом используя локальное состояние и эффекты отдельно:
function Form() {
// 在组件内直接定义一些state变量
const [name, setName] = useState('Mary');
const [surname, setSurname] = useState('Poppins');
// 我们将部分state和effects移至custom hook
const width = useWindowWidth();
// ...
}
function useWindowWidth() {
// 在custom hook内定义一些state变量
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
// ...
});
return width;
}
Если вы разрешаете только один вызов на компонентuseState()
, вы потеряете возможность вводить состояние с помощью пользовательских хуков, что является ключом к настраиваемым хукам.
Ошибка № 2: Конфликты имен
Распространенное предложение состоит в том, чтобы создавать компоненты внутриuseState()
Получает ключевой параметр уникального идентификатора (строка и т. д.) для различения переменных состояния.
Это немного отличается от этой идеи, но выглядит примерно так:
// ⚠️ This is NOT the React Hooks API
function Form() {
// 我们传几种state key给useState()
const [name, setName] = useState('name');
const [surname, setSurname] = useState('surname');
const [width, setWidth] = useState('width');
// ...
Это пытается избавиться от последовательного вызова зависимостей (клавиша отображения), но создает другую проблему — конфликты имен.
Конечно, за исключением ошибок, вы не сможете вызвать один и тот же компонент дважды.useState('name')
, это случайное появление можно отнести к другим произвольным ошибкам, однако при использованииcustom hookВы всегда будете сталкиваться с ситуациями, когда захотите добавить или удалить переменные состояния и эффекты.
В этом предложении каждый раз, когда вы добавляете новую переменную состояния в пользовательский хук, можно сломать любой компонент, который ее использует (прямо или косвенно), потому чтоВозможно, уже существует переменная с таким именемвнутри компонента.
это нетОптимизация для измененийAPI, текущий код всегда может выглядеть "изящно", но он очень хрупок в ответ на изменения требований, мы должны начать сошибкауроки выучены.
На практике предложение Hooks решает эту проблему, полагаясь на последовательный вызов: даже если оба Hooks используютname
переменные состояния, они также изолированы друг от друга, каждый вызовuseState()
будет независимым
«Единица памяти».
Есть и другие способы устранения этого недостатка, но у этих подходов есть свои недостатки. Давайте подробно изучим этот вопрос.
Ошибка №3: один и тот же хук нельзя вызвать дважды
ДатьuseState
Другое производное предложение для «keying» состоит в том, чтобы использовать что-то вроде Symbol, чтобы не было конфликта, верно?
// ⚠️ This is NOT the React Hooks API
const nameKey = Symbol();
const surnameKey = Symbol();
const widthKey = Symbol();
function Form() {
// 我们传几种state key给useState()
const [name, setName] = useState(nameKey);
const [surname, setSurname] = useState(surnameKey);
const [width, setWidth] = useState(widthKey);
// ...
Это предложение кажется правильным для извлеченногоuseWindowWidth
Крюк работает:
// ⚠️ This is NOT the React Hooks API
function Form() {
// ...
const width = useWindowWidth();
// ...
}
/*********************
* useWindowWidth.js *
********************/
const widthKey = Symbol();
function useWindowWidth() {
const [width, setWidth] = useState(widthKey);
// ...
return width;
}
Но если вы попробуете обработку извлеченного ввода, это не удастся:
// ⚠️ This is NOT the React Hooks API
function Form() {
// ...
const name = useFormInput();
const surname = useFormInput();
// ...
return (
<>
<input {...name} />
<input {...surname} />
{/* ... */}
</>
)
}
/*******************
* useFormInput.js *
******************/
const valueKey = Symbol();
function useFormInput() {
const [value, setValue] = useState(valueKey);
return {
value,
onChange(e) {
setValue(e.target.value);
},
};
}
(Я признаюuseFormInput()
Хуки не особенно полезны, но вы можете себе представить, что они обрабатывают такие вещи, как проверка и грязные флаги состояния, такие какFormik. )
Можете ли вы обнаружить эту ошибку?
мы называемuseFormInput()
дважды, ноuseFormInput()
всегда вызывается с одним и тем же ключомuseState()
,так:
const [name, setName] = useState(valueKey);
const [surname, setSurname] = useState(valueKey);
Мы снова столкнулись.
На практике предложение Hooks не имеет этой проблемы, потому чтокаждый разпередача useState()
получит отдельное состояние. Использование вызовов с фиксированным порядком избавляет нас от беспокойства о конфликтах имен.
Недостаток № 4: проблема бриллианта (проблема многослойного наследования)
Технически это тот же недостаток, что и предыдущий, но его дурная слава заслуживает упоминания, даже в Википедии. (Иногда его еще называют «смертоносным бриллиантом смерти» — круто!)
Наша собственная система миксбыло больно.
НапримерuseWindowWidth()
а такжеuseNetworkStatus()
Эти два пользовательских хука могут использовать что-то вродеuseSubscription()
Такой пользовательский хук выглядит следующим образом:
function StatusMessage() {
const width = useWindowWidth();
const isOnline = useNetworkStatus();
return (
<>
<p>Window width is {width}</p>
<p>You are {isOnline ? 'online' : 'offline'}</p>
</>
);
}
function useSubscription(subscribe, unsubscribe, getValue) {
const [state, setState] = useState(getValue());
useEffect(() => {
const handleChange = () => setState(getValue());
subscribe(handleChange);
return () => unsubscribe(handleChange);
});
return state;
}
function useWindowWidth() {
const width = useSubscription(
handler => window.addEventListener('resize', handler),
handler => window.removeEventListener('resize', handler),
() => window.innerWidth
);
return width;
}
function useNetworkStatus() {
const isOnline = useSubscription(
handler => {
window.addEventListener('online', handler);
window.addEventListener('offline', handler);
},
handler => {
window.removeEventListener('online', handler);
window.removeEventListener('offline', handler);
},
() => navigator.onLine
);
return isOnline;
}
Вот реальный рабочий пример.Автору пользовательского хука должно быть безопасно подготовить или прекратить использование другого пользовательского хука, не беспокоясь о том, был ли он «использован» где-то в цепочке..
(В качестве контрпримера устаревший ReactcreateClass()
Миксины не позволяют вам сделать это, и иногда у вас есть два миксина, оба из которых вам нужны, но несовместимы друг с другом, потому что они расширяют один и тот же «базовый» миксин. )
Вот наши "бриллианты": 💎
/ useWindowWidth() \ / useState() 🔴 Clash
Status useSubscription()
\ useNetworkStatus() / \ useEffect() 🔴 Clash
Использование фиксированного порядка вызовов решает эту проблему естественным образом:
/ useState() ✅ #1. State
/ useWindowWidth() -> useSubscription()
/ \ useEffect() ✅ #2. Effect
Status
\ / useState() ✅ #3. State
\ useNetworkStatus() -> useSubscription()
\ useEffect() ✅ #4. Effect
С вызовами функций не возникает "алмазной" проблемы, поскольку они образуют древовидную структуру. 🎄
Недостаток № 5: Идея копирования и вставки перепутана
Возможно, мы можем спасти предложение о состоянии «ключа», введя какое-то пространство имен, есть несколько разных способов сделать это.
Один из способов — использовать замыкания для изоляции ключей состояния, что требует, чтобы вы оборачивали каждый хук функцией, когда вы «создаете» пользовательские хуки:
/*******************
* useFormInput.js *
******************/
function createUseFormInput() {
// 每次实例化都唯一
const valueKey = Symbol();
return function useFormInput() {
const [value, setValue] = useState(valueKey);
return {
value,
onChange(e) {
setValue(e.target.value);
},
};
}
}
Этот подход очень громоздкий, и одна из целей дизайна хуков — избежать использования компонентов более высокого порядка и глубоко вложенных функций свойств рендеринга. Здесь мы должны использоватьЛюбые«Создавайте экземпляры» пользовательских хуков — и используйте созданную функцию только один раз в теле компонента, что гораздо сложнее, чем прямой вызов хуков.
Кроме того, вы должны сделать это дважды, чтобы компонент использовал пользовательский хук. Один раз на верхнем уровне (или внутри функции при написании пользовательского хука) и один раз при финальном вызове. Это означает, что даже для небольшого изменения вам придется переключаться между объявлением верхнего уровня и функцией рендеринга:
// ⚠️ This is NOT the React Hooks API
const useNameFormInput = createUseFormInput();
const useSurnameFormInput = createUseFormInput();
function Form() {
// ...
const name = useNameFormInput();
const surname = useNameFormInput();
// ...
}
Вам также нужно очень точное именование, всегда учитывайте «два уровня» именования - что-то вродеcreateUseFormInput
такая заводская функция иuseNameFormInput
,useSurnameFormInput
Такой экземпляр Хуки.
Если вы вызовете один и тот же пользовательский хук «экземпляр» дважды одновременно, у вас возникнут конфликты состояний. На самом деле приведенный выше код как раз и есть такая ошибка — нашли? Так должно быть:
const name = useNameFormInput();
const surname = useSurnameFormInput(); // Not useNameFormInput!
Эти проблемы не являются непреодолимыми, но я думаю, что их будет больше.Правила хуковсопротивление больше.
Важно отметить, что они ломают счеты для копирования и вставки. Такие пользовательские хуки по-прежнему можно использовать без оболочки, но их можно вызвать только один раз (что может вызвать проблемы при использовании). К сожалению, когда кажется, что API работает, как только вы понимаете, что где-то в цепочке есть конфликт, вы должны обернуть все, что определено.
Недостаток № 6: нам по-прежнему нужен инструмент для проверки кода
Есть еще один способ использовать состояние ключа, чтобы избежать коллизий, если вы знаете, может быть очень разозлен, потому что мне это не нравится, извините.
Идея в том, что каждый раз, когда вы пишете кастомный хуккомбинациятакой ключ:
// ⚠️ This is NOT the React Hooks API
function Form() {
// ...
const name = useFormInput('name');
const surname = useFormInput('surname');
// ...
return (
<>
<input {...name} />
<input {...surname} />
{/* ... */}
</>
)
}
function useFormInput(formInputKey) {
const [value, setValue] = useState('useFormInput(' + formInputKey + ').value');
return {
value,
onChange(e) {
setValue(e.target.value);
},
};
}
По сравнению с другими альтернативными предложениями, это мне меньше всего не нравится, и я не думаю, что оно многого стоит.
После многократного вызова хука или конфликта с другими хуками код можетнеожиданный выводПередан неуникальный или синтетически недопустимый ключ. Хуже того, если это произойдет при определенных условиях (мы попытаемся «исправить» это, верно?), может пройти некоторое время, прежде чем возникнет конфликт.
Хотим напомнить всем помнить, что все кастомные хуки, помеченные ключами, хрупкие, они не только увеличивают нагрузку на рантайм (не забывайте, что они конвертируются включ) и будет постепенно увеличивать размер пакета.Но если нам нужно напомнить один вопрос, какой это вопрос??
Этот подход может работать, если вам нужно объявить состояние и эффекты в условных выражениях, но по прошлому опыту я нашел его запутанным. На самом деле, я не помню, чтобы кто-нибудь определял в условных предложенияхthis.state
илиcomponentMount
из.
Что именно означает этот код?
// ⚠️ This is NOT the React Hooks API
function Counter(props) {
if (props.isActive) {
const [count, setCount] = useState('count');
return (
<p onClick={() => setCount(count + 1)}>
{count}
</p>;
);
}
return null;
}
когдаprops.isActive
дляfalse
Времяcount
Это зарезервировано? или из-заuseState('count')
сбросить без звонкаcount
?
Что происходит с эффектом, если условием является сохранение состояния?
// ⚠️ This is NOT the React Hooks API
function Counter(props) {
if (props.isActive) {
const [count, setCount] = useState('count');
useEffect(() => {
const id = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(id);
}, []);
return (
<p onClick={() => setCount(count + 1)}>
{count}
</p>;
);
}
return null;
}
не сомневаюсь, что не будетprops.isActive
первый раз былtrue
Доработает, но как только становитсяtrue
, он перестанет работать? когдаprops.isActive
Вfalse
Будет ли сброшен интервал? Если это так, это сбивает с толку, что эффект ведет себя иначе, чем состояние (когда мы говорим не сбрасывать). Если эффект продолжает работать, внешний слой эффектаif
Также сбивает с толку то, что эффекты больше не контролируются, разве мы не говорили, что хотим, чтобы эффекты контролировались в зависимости от условий?
Если мы не «используем» состояние во время рендеринга, а сбрасываем его, если есть несколькоif
ветвь содержитuseState('count')
Но только один из них будет работать в данный момент времени, что произойдет? Это действительный код? Если наша основная идея состоит в том, чтобы «распространять по ключу», то зачем ее «отбрасывать»? Хочет ли разработчик перейти от компонента после этогоreturn
Как насчет сброса всего состояния? На самом деле, если нам действительно нужно сбросить состояние, мы можем сделать это явным, извлекая компонент:
function Counter(props) {
if (props.isActive) {
// Clearly has its own state
return <TickingCounter />;
}
return null;
}
В любом случае, это может стать «лучшей практикой» для решения этих запутанных проблем, поэтому, какой бы способ вы ни выбрали для объяснения, я думаю, что условиеутверждениеКак состояние и эффект семантики очень странные, вы можете неосознанно почувствовать.
Если это еще и напоминание - необходимость правильно комбинировать ключи становится "бременем", которое не дает нам ничего из того, что мы хотим. Однако отказ от этого требования (и возврат к исходному предложению) дает нам нечто, что позволяет безопасно копировать и вставлять код компонента в пользовательский хук без необходимости в пространствах имен, уменьшенный размер пакета и небольшое повышение эффективности (отсутствие поиска по карте). требуется).
Потихоньку разбирайся.
Ошибка № 7: Хуки не могут передавать значения
Одной из лучших особенностей хуков является возможность передавать значения между ними.
Вот фиктивный пример выбора получателей сообщения, который показывает, находится ли текущий выбранный приятель в сети:
const friendList = [
{ id: 1, name: 'Phoebe' },
{ id: 2, name: 'Rachel' },
{ id: 3, name: 'Ross' },
];
function ChatRecipientPicker() {
const [recipientID, setRecipientID] = useState(1);
const isRecipientOnline = useFriendStatus(recipientID);
return (
<>
<Circle color={isRecipientOnline ? 'green' : 'red'} />
<select
value={recipientID}
onChange={e => setRecipientID(Number(e.target.value))}
>
{friendList.map(friend => (
<option key={friend.id} value={friend.id}>
{friend.name}
</option>
))}
</select>
</>
);
}
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
const handleStatusChange = (status) => setIsOnline(status.isOnline);
useEffect(() => {
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
При смене получателейuseFriendStatus
Крюк отпишется от статуса предыдущего друга и подпишется на следующего.
Это работает, потому что мы можемuseState()
Значение, возвращаемое хуком, передаетсяuseFriendStatus()
Крюк:
const [recipientID, setRecipientID] = useState(1);
const isRecipientOnline = useFriendStatus(recipientID);
Передача значений между хуками очень полезна. Например:React SpringМожно создать тянущуюся анимацию, в которой несколько значений «следуют» друг за другом:
const [{ pos1 }, set] = useSpring({ pos1: [0, 0], config: fast });
const [{ pos2 }] = useSpring({ pos2: pos1, config: slow });
const [{ pos3 }] = useSpring({ pos3: pos2, config: slow });
(Этоdemo. )
Предложение добавить параметры по умолчанию при инициализации Хука или написать Хук в форме декоратора усложняет реализацию логики в данном случае.
Если вы не вызываете хуки внутри тела функции, вы не сможете легко передавать значения между ними. Вы можете изменить структуру этих значений, чтобы их не нужно было передавать между несколькими слоями компонентов, или вы можете использоватьuseMemo
для хранения результатов расчета. Но вы также не можете ссылаться на эти значения в эффектах, потому что их нельзя получить в замыканиях. Есть способы решить эти проблемы с определенными соглашениями, но они требуют от вас «вычисления» входных и выходных данных в уме, что противоречит прямолинейному стилю React.
Передача значений между хуками — это ядро нашего предложения, паттерн Render props — это первое, что вы можете придумать без хуков, но что-то вродеComponent ComponentТакая библиотека подходит не для всех сценариев, с которыми вы сталкиваетесь, в ней много синтаксического шума из-за «неправильной иерархии». Хуки реализуют передачу по значению с плоской иерархией, а вызовы функций — самый простой способ передачи по значению.
Ошибка № 8: громоздкие шаги
В этой категории много предложений. Они пытаются заставить React максимально избавиться от хуков, и большинство из них делают следующее: пустьthis
Имея встроенные хуки, делая их дополнительными параметрами повсеместно в React и не только.
я думаюОтвет от СебастьянаБолее убедительно в этом смысле, чем мое описание, предлагаю вам разобраться в «инъекционной модели».
Достаточно сказать, что это не имеет ничего общего с тем, что программисты склонны использоватьtry
/catch
Код ошибки в методе захвата тот же, также по сравнению с AMD, переданным нами.require
Заявление "show" мы предпочитаемimport
(или CommonJSrequire
) модуля ES.
// 有谁想念 AMD?
define(['require', 'dependency1', 'dependency2'], function (require) {
var dependency1 = require('dependency1'),
var dependency2 = require('dependency2');
return function () {};
});
Да, AMD могла бы быть более "честной", утверждая, что модули не загружаются синхронно в среде браузера, но когда вы это знаете, напишитеdefine
Бутерброды становятся бесполезными.
try
/catch
,require
И React Context API — это реальные примеры, когда мы предпочитаем «эмбиентный» стиль прямому декларативному использованию (хотя обычно мы предпочитаем простой стиль), и я думаю, что хуки попадают в эту категорию.
Это похоже на то, когда мы объявляем такие компоненты, как fromReact
ловитьComponent
Присоединяйся. Если мы экспортируем каждый компонент как фабрику, возможно, наш код будет более несвязанным:
function createModal(React) {
return class Modal extends React.Component {
// ...
};
}
Но на практике это оказывается излишним и раздражающим. Когда мы действительно хотим каким-то образом поймать React, мы должны сделать это на уровне модульной системы.
То же самое относится и к хукам. Тем не менее, какОтвет от Себастьянаупоминается втехническиможно сделать изreact
Импортируйте хуки разных реализаций «напрямую» в . (мои предыдущие статьиупомянул. )
Еще одна идея принудительного усложнения — поставить крючкимонадический (монадический)или добавить что-то вродеReact.createHook()
Такая концепция класса. Все, кроме времени выполнения, которое добавляет вложенность, теряет преимущества обычных функций:легко отлаживать.
В процессе отладки никакой код библиотеки классов не смешивается с обычными функциями, а поток внутренних значений компонентов может быть четко известен, чего сложно добиться косвенным путем. Например, вдохновленные компонентами более высокого порядка («хуки-декораторы») или реквизитами рендеринга (adopt
предложения или генераторыyield
д.) и подобные схемы, у всех такие проблемы. Косвенность также усложняет статическую типизацию.
Как я упоминал ранее, этот пост не будет исчерпывающим, в других предложениях есть много интересных вопросов, некоторые из которых более неясны (например, связанные с параллелизмом и расширенной компиляцией), которые могут быть для другого поста в будущей теме.
Хуки не безупречны, но это лучший компромисс, который мы можем найти для решения этих проблем. и некоторые из насеще нужно исправитьвещи, эти проблемы более неудобны в хуках, чем в классах, о чем также будет написано в других статьях.
Независимо от того, освещаю ли я ваши любимые альтернативы, я надеюсь, что эта статья поможет проиллюстрировать наш мыслительный процесс и критерии, которые мы учитываем при выборе API. Как видите, многое (например, копирование и вставка, перемещение кода, добавление и удаление зависимостей так, как вы хотите) должно былоОптимизация для изменений. Надеюсь, разработчики React оценят принятые нами решения.
перевести оригиналWhy Do React Hooks Rely on Call Order?(2018-12-13)