Comments 11
Почти никогда не стоит. Если в реакте меняется стейт, значит, что-то должно быть перерисовано. Оборачивать вообще все дорого как с точки зрения производительности, так и с точки зрения багов
Оборачивать кое-что иногда имеет смысл
Именно! Оборачивать только, когда на то есть веская причина. Даже если кажется, что "операция дорогая, надо обернуть", если видимых проблем с перформансом нет, то не имеет смысла почти 100%
Видел проекты на 30+ мб рукописного реактовского кода, где обернуто абсолютно все и видел такие же проекты, где ничего не обернуто. Это все конечно ЦРМки были, но все же разницы не чувствуется
const Display = React.memo(function Display({ data }) {
console.log('Рендер Display');
return <div>{data.value}</div>;
});
function App() {
const [count, setCount] = React.useState(0);
const data = React.useMemo(() => ({ value: 'Статичный текст' }), []);
return (
<div>
<Display data={data} />
<button onClick={() => setCount(count + 1)}>Увеличить</button>
</div>
);
}
А здесь useMemo чтобы что? Чтобы на каждый рендер была проверка пустого массива зависимостей? Почему не в реф?
В этой статье я рассматривал хуки useMemo, useCallback и HOC React.memo. Чтобы показать решение проблемы с изменяющейся ссылкой у объектов, массивов и функций, для примера был использован useMemo. Но согласен, что можно было бы сделать это и через реф, возможно, об использовании рефа для оптимизации я напишу в следующей статье)
Хорошая статья, но не хватает реальных кейсов и измерений. Добавьте примеры с анализом производительности, чтобы лучше показать, когда мемоизация действительно полезна
очень полезно! спасибо большое!)
Ответ
На первый взгляд, оборачивание increment в useCallback и Button в React.memo должно предотвратить ненужные перерисовки Button. Но в данном случае выигрыш в производительности будет либо незначительным, либо его не будет вообще.
Ответ не совсем верный. Если кейс именно как в статье - ускорения не будет вообще. Так как ваш инкремент мемоизируется следующим образом:
const increment = React.useCallback(() => setCount(count + 1), [count]);
С зависимостью - count
. А значит коллбек будет пересоздаваться после каждого клика на кнопку. Значит и кнопка будет рендериться заново после каждого клика, потому как ссылка на коллбек новая.
Что бы этого не было, нужно создавать коллбек без зависимости (как вы делали ранее):
const increment = React.useCallback(() => setCount((c) => c + 1), []);
И мне кажется нужно было специально обратить внимание на эту фишку создания коллбека без зависимости.
Именно данная зависимость на count
и ломает полностью оптимизацию в вопросе. А если сделать коллбек без зависимости - тогда уже можно рассуждать о том, будет ли перформанс буст и имеет ли смысл, но так он хотя бы возможен.
Отдельно про рассуждения про сложность, целесообразность, ..., скорость оптимизации из вашего вопроса:
Для тех кто это все умеет - эта информация не ценна, а для тех кто новичек - они тут ничего не запомнят и не поймут, будет просто как вода. Потому что у вас просто общие рассуждения, по верхам.
Нужно делать как в вашем же утверждении в пунктах: все мерять и сравнивать (скорость, память, сложность, размер, ...). Без замеров перформанс статьи неполны.
По вашему вопросу:
Вот есть у нас простой компонет Button, мы решили что раз он у нас простой то мы не будем мемоизировать кэллбеки для него. Компонент часто используется в сотнях мест. А вот чуть попозже нам к нему необходимо добавить состояние disabled, вроде бы небольшая доработка и компонент все еще достаточно прост. Но еще чуть позже мы добавляем лоадер, далее добавились выводы иконок еще чуть позже тултипы и т.д.
И вот наш простой компонент уже не такой уж и простой. Но его путь к "непростому" был растянут во времени и скорее всего еще и разными людьми. И вот когда то надо будет идти по всем местам где используется этот комопнент и делать оптимизации, что довольно сложно понять в моменте.
И раз, как вы и сказали, выигрыш в произоводительности будет незначительным или не будет вообще, значит и вреда особого не будет? Дак не стоит ли нам просто все оборачивать в useCallback?
По поводу усложнения читаемости кода: тут все наоборот единообразие его повышает имхо.
Взгляд с другой стороны на useMemo, useCallback и React.memo в React: когда их стоит использовать