Реакция: обновление состояния в условном setTimeout внутри componentDidMount не перезагружает компонент

Обновлено: Я понял проблему вскоре после публикации этого сообщения. Смотрите мой ответ ниже.

Я действительно озадачен, почему мой компонент не перезагружается после обновления состояния. Это полный код компонента (за вычетом импорта / экспорта) с аннотациями:

class About extends Component {
    state = {
        introIsRunning: true,
        animationStep: 1,
        indent: 0,
        steps: {
            1: ["placeholder"],
            2: ["placeholder"],
            3: ["placeholder"],
            4: ["placeholder"],
            5: ["placeholder"],
            6: ["placeholder"],
        },
        content: [],
    };

Моя цель - показывать новую строку контента каждые пять секунд, пока я не дойду до конца шагов, на котором я останавливаюсь.

Прежде чем вносить какие-либо изменения в состояние, я проверяю, верно ли значение introIsRunning. Затем я проверяю, дошли ли мы до конца шагов; если это так, я устанавливаю introIsRunning на false, что предотвратит дальнейшие изменения состояния.

(Глядя на это еще раз, я вижу, что наличие логической а также проверки animationStep довольно излишне, когда я могу просто проверить animationStep и оставить все как есть. Я не понимаю, почему это может быть проблемой, так что продолжаем. ..)

    componentDidMount = () => {
        if (this.state.introIsRunning) {
            if (this.state.animationStep > 6 {
                this.setState({ introIsRunning: false });
            }

Если это первый шаг, мне не нужна задержка перед отображением первой строки. Но если хотя бы первая строка уже была возвращена, я хочу подождать 5 секунд, прежде чем добавлять следующую. Однако, поскольку нулевая задержка вызовет немедленное изменение состояния, которое потенциально может вызвать проблемы, я добавил 5-секундную задержку к рендерингу первой строки, чтобы убедиться, что это не вызывает мою проблему.

            let animationDelay = 5000;
            if (this.state.animationStep > 1) {
                animationDelay = 10000;
            }

            console.info('state before timeout:', this.state);

В журнале консоли «состояние до тайм-аута» отображается animationStep: 1, а содержимое представляет собой пустой массив. Как и ожидалось.

После заданной задержки я обновляю состояние с правильным содержанием шага и увеличиваю шаг, чтобы на следующей итерации он загрузил шаг 2 и перешел к 3 и т. д.

setupContent просто добавляет новый объект с соответствующим содержимым в массив содержимого состояния, который используется в методе рендеринга для создания фактического компонента.

            setTimeout(() => {
                this.setState({
                    content: this.setupContent(this.state.steps[this.state.animationStep]),
                    animationStep: this.state.animationStep + 1,
                });
            }, animationDelay);

            // debugging
            setTimeout(() => {
                console.info('why am I still here? state is:', this.state);
            }, 15000);
        }
    }

    setupContent = content => {
        let updatedContent = [...this.state.content];

        const id = "line_" + this.state.animationStep;

        updatedContent.push({
            id: id,
            number: this.state.animationStep,
            indent: this.state.indent,
            content: content,
        });
    }

«Почему я все еще здесь?» журнал консоли фактически показывает правильно обновленное состояние. AnimationStep теперь равен 2, а массив содержимого содержит один объект, созданный в соответствии со спецификациями setupContent.

    render() {
        return (
            <div className = "container">
                {this.state.content.map(line => (
                    <Line
                        key = {line.id}
                        id = {line.id}
                        number = {line.number}
                        indent = {line.indent}
                    >
                        {line.content}
                    </Line>
                ))}
            </div>
        );
    }
}

Это правильно превращает мой объект содержимого в функциональный компонент, который отображает то, что я хочу. Однако он никогда не переходит к следующему шагу. После правильного проверяемого обновления состояния оно просто сидит здесь. Я искал и выполнил столько отладки, сколько мог, но я действительно не имею никакого представления о том, почему состояние будет обновляться без перезагрузки компонента.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
577
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вау, я чувствую себя действительно глупо, когда выясняю это через несколько минут после публикации вопроса, но проблема, конечно же, заключалась в том, что я делал все эти проверки в componentDidMount, что происходит только один раз. Я переместил весь код из componentDidMount в его собственную функцию, которую теперь вызываю в componentDidMount а также componentDidОбновлять. Теперь все работает как положено. Мне действительно нужна резиновая уточка ...

Другие вопросы по теме