🌍 Привет мир! 👋
🌍 Привет мир! 👋
Хочется чтобы весь код работал с первого раза и более того, чтобы в нем вообще не было багов, но мир далеко не идеален, и сегодня в разборе проблема которую недавно я обнаружил в одном из проектов.
📊 Cтатистика
Мне стало интересно, сколько же багов создает средний разработчик, понятно что здесь миллион факторов которые влияют на значения, но все же ➕➖ что-то можно посчитать.
💡 Я нашел вот такую статистику, которую предоставила Coralogix компания.
❗ В среднем разработчик создает 70 ошибок на каждые 1000 строк кода.
❗ 15 ошибок на 1000 строк кода доходят до пользователей. Исправление ошибки занимает в 30 раз больше времени, чем написание одной строки кода.
❗ 75% времени разработчика уходит на отладку (1500 часов в год!).
❗ Только в США ежегодно тратится 113 миллиардов долларов на выявление и исправление дефектов продуктов.
💻 Проблема найденная в коде
Есть обычный функциональный компонент, в реальной проблеме он был немного больше и запутаннее, я оставил только самый сок.
🧠 Подумайте в чем здесь может быть проблема, получится ли у вас сразу спрогнозировать проблему?
Ответ: Компонент будет уходить в Infinite Render Loop из-за того, что каждый раз создается initialTasks с пустым массивом.
👀 На первый взгляд проблема будет не всем очевидна. При обычном сценарии компонент может вызываться в одном месте и в этом случае передается
Но что если появилась задача имплементировать компонент в другом месте❓ Вы без всяких сложностей, добавляете новый функционал, но не передаете пропс
👇 В таком случае вы получаете:
🔎 Проблема заключается в том, что когда родительский компонент вызывает
Это означает, что, хотя значение
🛠️ Как итог каждый раз обновляется состояние
❗ Если такая проблема не попадает на глаз сразу, то в дальнейшем это может привести к тяжелым поискам и временным затратам.
📝 Решения
1️⃣ Использовать внешнюю константу.
2️⃣ Использовать мемоизацию. Это гарантия того, что значение по умолчанию для
🙂 Всем хорошей недели и чистого кода!
💬 Делитесь своим мнением в комментариях👇! Если вам понравилась статья, не забудьте поставить лайк! 👍
#REACT
Хочется чтобы весь код работал с первого раза и более того, чтобы в нем вообще не было багов, но мир далеко не идеален, и сегодня в разборе проблема которую недавно я обнаружил в одном из проектов.
📊 Cтатистика
Мне стало интересно, сколько же багов создает средний разработчик, понятно что здесь миллион факторов которые влияют на значения, но все же ➕➖ что-то можно посчитать.
💡 Я нашел вот такую статистику, которую предоставила Coralogix компания.
❗ В среднем разработчик создает 70 ошибок на каждые 1000 строк кода.
❗ 15 ошибок на 1000 строк кода доходят до пользователей. Исправление ошибки занимает в 30 раз больше времени, чем написание одной строки кода.
❗ 75% времени разработчика уходит на отладку (1500 часов в год!).
❗ Только в США ежегодно тратится 113 миллиардов долларов на выявление и исправление дефектов продуктов.
💻 Проблема найденная в коде
Есть обычный функциональный компонент, в реальной проблеме он был немного больше и запутаннее, я оставил только самый сок.
const TodoComponent = ({ initialTasks = [] }) => {
const [tasks, setTasks] = useState();
useEffect(() => {
setTasks({
taskCount: initialTasks.length,
});
}, [initialTasks]);
const renderTaskCount = tasks?.taskCount ?? 0;
return (
<>
<h1>TodoComponent</h1>
<p>Task Count: {renderTaskCount}</p>
</>
);
};
🧠 Подумайте в чем здесь может быть проблема, получится ли у вас сразу спрогнозировать проблему?
Ответ: Компонент будет уходить в Infinite Render Loop из-за того, что каждый раз создается initialTasks с пустым массивом.
👀 На первый взгляд проблема будет не всем очевидна. При обычном сценарии компонент может вызываться в одном месте и в этом случае передается
initialTasks.<TodoComponent initialTasks={[1, 2, 3]} />
Но что если появилась задача имплементировать компонент в другом месте❓ Вы без всяких сложностей, добавляете новый функционал, но не передаете пропс
initialTasks, так как в нем нет необходимости.<TodoComponent />
👇 В таком случае вы получаете:
Warning: Maximum update depth exceeded.
This can happen when a component calls setState inside useEffect,
but useEffect either doesn't have a dependency array,
or one of the dependencies changes on every render
🔎 Проблема заключается в том, что когда родительский компонент вызывает
TodoComponent и не передает initialTasks, то значение по умолчанию = [] каждый раз создается заново.Это означает, что, хотя значение
initialTasks одно и то же (пустой массив), это новая ссылка при каждом рендеринге. И все бы ничего, но initialTasks идет как dependencies в useEffect.🛠️ Как итог каждый раз обновляется состояние
setTasks, которое приводит к re-render компонента и создании нового массива → Infinite Render Loop.❗ Если такая проблема не попадает на глаз сразу, то в дальнейшем это может привести к тяжелым поискам и временным затратам.
📝 Решения
1️⃣ Использовать внешнюю константу.
const defaultInitialTasks = [];
const TodoComponent = ({ initialTasks = defaultInitialTasks }) => ...
2️⃣ Использовать мемоизацию. Это гарантия того, что значение по умолчанию для
initialTasks не изменится между рендерами, если оно явно не изменено. const defaultInitialTasks = useMemo(() => initialTasks || [], [initialTasks]);
useEffect(() => {
setTasks({
taskCount: defaultInitialTasks.length,
});
}, [defaultInitialTasks]);
🙂 Всем хорошей недели и чистого кода!
💬 Делитесь своим мнением в комментариях👇! Если вам понравилась статья, не забудьте поставить лайк! 👍
#REACT

Хотите больше таких постов?
Подпишитесь на канал и читайте продолжение в Telegram.