React Native: анимация при отключении компонентов
У меня есть собственный модальный, который скользит в componentDidMount
:
componentDidMount() {
Animated.timing(this._animatedValue.y, {
duration: 200,
toValue: 0
}).start()
}
Хорошо, это было легко. Тем не менее, мне также нравится сдвигать модальность, когда компонент размонтируется. Для меня componentWillUnmount()
будет чувствовать себя правильно, поскольку это элегантный декларативный способ:
componentWillUnmount() {
Animated.timing(this._animatedValue.y, {
duration: 200,
toValue: deviceHeight
}).start()
}
Но это, конечно, работает не, потому что React не ждет, пока я не закончу свою анимацию.
Итак, в настоящее время я обхожу это с помощью специальной функции:
closeModal() {
Animated.timing(this._animatedValue.y, {
duration: C.filterModalDuration,
toValue: deviceHeight
}).start()
InteractionManager.runAfterInteractions(() => {
this.props.UnmountThisComponent()
})
}
Это, конечно, не так элегантно, но работает. Тем не менее, боль начинается, если мне нужно вызвать эту функцию из компонента, находящегося далеко внизу в дереве компонентов, т.е. Мне нужно вручную передать эту функцию через onUnmount={()=> closeModal()}
, а затем с помощью onUnmount={this.props.onUnmount}
снова и снова...
Тогда я подумал, что смогу решить это с помощью redux и redux-connect. Я подумывал вызвать изменение состояния редукции из дочерних компонентов, которое затем вызывало бы функцию через componentWillRecieveProps()
следующим образом:
componentWillReceiveProps (nextProps) {
if (nextProps.closeFilter === true) {
this.closeModal()
}
}
Однако это кажется довольно халатным и императивным.
Есть ли способ решить эту проблему элегантным/декларативным способом?
Ответы
Ответ 1
Я бы не использовал InteractionManager.runAfterInteractions
для выполнения после завершения анимации. Я рекомендую использовать обратный вызов start
.
Animated.timing(this.animatedValue, {}).start(() => this.props.closeModal())
Есть такие вещи, как https://github.com/mosesoak/react-native-conductor, которые могут помочь вам координировать глубокую анимацию и создать резервную копию. Это использует context
.
Вы также можете использовать сокращение, как вы пробовали, но я бы использовал componentDidUpdate
, а не componentWillReceiveProps
.
Причина в том, что безопасно вызывать setState
в компоненте, в котором у вас есть componentWillReceiveProps
.
Если вы вызываете dispatch
внутри componentWillReceiveProps
, это приведет к тому, что setState
в других компонентах приведет к разрыву приложения.
В целом: я бы рекомендовал этот поток. (Close Action Initiated) = > Animate Modal Closed = > in start(() => {})
callback вызывает a setState
или задает фрагмент данных в вашем хранилище redux
, который затем будет unmount
ваш модальный, который теперь скрыт.
Таким образом вы получаете анимацию unmount.
Если вы используете маршрутизацию типа react-navigation
, я рекомендую настроить стиль навигации mode: "modal"
. Таким образом, для вас будут заботиться об отключении/монтаже модальных анимаций.
Ответ 2
componentWillReceiveProps
кажется идеально подходит, поскольку он намерен делать действия на основе следующих реквизитов. Это идеальный вариант, когда родители хотят инициировать действия над своими детьми (даже на этом не является образцом Реагирования, когда дети называют функции родителей, а родители получают события от детей).