Пейджер

🌍 Привет мир!

🌍 Привет мир!

Знаю что среди вас есть разработчики которые в основе использует React при написания кода, и вот наступила наконец-то и ваша очередь =). В комментариях мне задавали вопрос, а как будет работать несколько useEffect с useState внутри, поэтому сегодня поговорим как раз про это.

🚀 Мотивация

На самом деле, писать код используя React, можно и без понимание этих вещей, но время от времени вы будете встречать баги, и и вас будут вопросы почему так, а еще на собеседовании могут спросить:
- А какая последовательность вывода логов?
Поэтому все-таки лучше погрузиться и не натыкаться на эти единичные проблемы.

🧐 Подумайте, в каком порядке появятся логи, strictMode не используется.

const App = () => {    
    const [version, setVersion] = useState(0);
    
    useEffect(() => {
        console.log('useEffect 1');
        setVersion((version) => version + 1);
    }, []);

    useEffect(() => {
        console.log(useEffect 3 version: ${version});
        const timer = setTimeout(() => {
            console.log(Timer for useEffect 3 done with version: ${version});
        }, 3000);

        return () => {
            clearTimeout(timer);
            console.log(useEffect 3 version: ${version} cleanup);
        };
    }, [version]);

    useEffect(() => {
        console.log(useEffect 2 version: ${version});
        const timer = setTimeout(() => {
            console.log(Timer for useEffect 2 done with version: ${version});
        }, 3000);

        return () => {
            console.log(useEffect 2 version: ${version} cleanup);
        };
    }, [version]);

    console.log('App');

    return <h1>hello world!</h1>;
};


📝 Вывод:
1. App 2. useEffect 1 3. useEffect 3 version: 0 4. useEffect 2 version: 0 5. App 6. useEffect 3 version: 0 cleanup 7. useEffect 2 version: 0 cleanup 8. useEffect 3 version: 1 9. useEffect 2 version: 1 10. Timer for useEffect 2 done with version: 0 11. Timer for useEffect 3 done with version: 1 12. Timer for useEffect 2 done with version: 1

📖 Чтение компонента выполняется сверху вниз.
⚙️ App - несмотря на то, что он является последним. Так происходит потому что весь код, за исключение хуков useEffects выполняется в render phase, фаза в которой происходят все вычисления и компонент готовится к отрисовке.

⚙️ useEffect 1 - выполнится следующим, выполняется однократно, так как нет зависимостей, только при монтировании компонента.

⚙️ useEffect 3, 2 -
последовательно, так как чтение сверху вниз, и с version = 0.

‼️ И тут наступает переломный момент, несколько важных пунктов:
💡 В первом useEffect есть setVersion, почему после вызова setVersion не происходит re-render и оставшиеся эффекты не пропускаются?
Потому что в реакте есть важный принцип batching, реакт выполняет до конца весь синхронный код, а обновление состояний ставится в очередь, которая будет разобрана перед следующей отрисовкой компонента.

💡 Для useEffect 3,2 - version = 0, потому что в текущей фазе, состояния уже установлены и обновления на лету из-за batching не происходит.

💡 Есть 2 таймаута, они асинхронные, реакт не будет ожидать их выполнения, а приступит к обновлению состояния, так как для этого был триггер setVersion.

‼️ Компонент делает re-render и выполняет очередь обновлений в которой version станет 1.

⚙️ Снова видим App, данная консоль выполняется каждый раз, как и любой другой код, который не отслеживается реактом и не мемоизирован.

⚙️ useEffect 1 - не запускается, так как зависимость пустая, вызывается только при монтировании.

⚙️ Перед очередным запуском useEffect 3,2 вызываются функции очистки, обратите внимание только один из асинхронных таймеров очищается и не будет выполнен.

⚙️ useEffect 3,2 - вызываются и происходит вывод уже с обновленным version = 1.

⚙️ И наконец таймеры, один из них был очищен, выполнен не будет, а второй выполнится, но с version = 0, так как в момент инициализации было замкнуто старое положения state. Остальные будут выполнены уже с version = 1.

💬 Делитесь своим мнением в комментариях👇! Если вам понравилась статья, не забудьте поставить лайк! 👍

#REACT
Медиа 1
Хотите больше таких постов?
Подпишитесь на канал и читайте продолжение в Telegram.
Подписаться на @ivanchikovitclub Открыть пост в Telegram