Я хочу создать компонент, подобный модальному, который получает логическое значение open / closed в качестве опоры, а затем сохраняет это значение в состоянии компонента. При закрытии модального окна я хочу обновить логическое свойство close, но подождите несколько секунд, прежде чем обновлять состояние компонента, чтобы я мог добавить классы перехода и анимировать выход.
С componentWillReceiveProps
я мог бы добиться этого, заключив this.setState
в таймаут и тем временем добавив классы. С новым API React 16.3 я вижу, что рекомендуется вместо этого использует getDerivedStateFromProps
.
Поскольку getDerivedStateFromProps
"должен возвращать объект в состояние обновления или значение null, чтобы указать, что новые свойства не требуют каких-либо обновлений состояния" (React docs), я хочу, чтобы метод выглядел примерно так:
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.menuIsOpen === false && prevState.menuIsOpen === true) {
return setTimeout(() => { menuIsOpen: false}, 1000);
}
return null;
}
Но это не работает. я прочел, что setTimeout
не возвращает значение, но мне интересно, есть ли более элегантное решение проблемы, чем возврат обещания.
Вы можете использовать componentDidUpdate
:
componentDidUpdate(prevProps){
// update your class names...
if (!this.props.menuIsOpen && this.state.menuIsOpen) {
setTimeout(() => this.setState({ menuIsOpen: false}), 1000);
}
}
Это правильно. Вы также захотите подумать о том, что должно произойти, если модальный режим открывается, закрывается и открывается снова в быстрой последовательности, поскольку у вас могут быть условия гонки, если вы также не отслеживаете что-то вроде isAnimating
в состоянии и осторожно сбрасываете его / отменяете таймауты когда необходимо. Как только вы заставите его работать, я бы, вероятно, предложил извлечь логику перехода в отдельный компонент <DelayProp>
с API рендеринга опоры, чтобы вы могли его повторно использовать.
Я бы добавил, что существует риск того, что setState может быть вызван на отключенном компоненте, выдающем ошибку, поскольку setTimeout является асинхронным.
Попробуйте делать то, что вы делали раньше, в
componentDidUpdate
вместоcomponentWillReceiveProps
.