Обновлено: Я понял проблему вскоре после публикации этого сообщения. Смотрите мой ответ ниже.
Я действительно озадачен, почему мой компонент не перезагружается после обновления состояния. Это полный код компонента (за вычетом импорта / экспорта) с аннотациями:
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>
);
}
}
Это правильно превращает мой объект содержимого в функциональный компонент, который отображает то, что я хочу. Однако он никогда не переходит к следующему шагу. После правильного проверяемого обновления состояния оно просто сидит здесь. Я искал и выполнил столько отладки, сколько мог, но я действительно не имею никакого представления о том, почему состояние будет обновляться без перезагрузки компонента.
Вау, я чувствую себя действительно глупо, когда выясняю это через несколько минут после публикации вопроса, но проблема, конечно же, заключалась в том, что я делал все эти проверки в componentDidMount, что происходит только один раз. Я переместил весь код из componentDidMount в его собственную функцию, которую теперь вызываю в componentDidMount а также componentDidОбновлять. Теперь все работает как положено. Мне действительно нужна резиновая уточка ...