次のような署名を持つスナックバーのようなステータス メッセージ コンポーネントを作成しようとしています。
<StatusMsg
open={this.state.isOpen}
message={this.state.msg}
onRequestClose={someFunc}
/>
"open" が true に設定されている場合、メッセージは画面にアニメーション表示され、一定時間そこにとどまり、その後再びアニメーション表示されなくなります。
したがって、以下のコードは正常に動作しますが、かなり一般的な使用例を除きます。古いメッセージが画面外にアニメーション化される前に、呼び出し元のコンポーネントが新しいメッセージを設定する場合。その場合、以下のコードは単に現在表示されているメッセージを置き換え、同じタイマーを使用します。
理想的には、新しいメッセージが追加されると、古いメッセージが最初に画面外でアニメーション化され、次に新しいメッセージでアニメーション化されます。(新しいメッセージ テキストが古いメッセージ テキストと同じであっても、これが確実に行われるようにしたいと思います。)
私はこのようなことをする方法を理解できないようです。私の推測では、StatusMsg は実際には、メッセージを含むアニメーション ビューを作成するためのファクトリである必要がありますが、それを機能させる方法がわかりません。具体的には、新しいメッセージの作成時に以前のメッセージを閉じる方法。
class StatusMsg extends Component {
state = { exited: false, moveHeightAnimated: new Animated.Value(HIDDEN_HEIGHT) }
timerAutoHide = null;
componentWillMount() {
if (!this.props.open) {
this.setState({ exited: true });
}
}
componentDidMount() {
if (this.props.open) {
this.show();
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.open && this.state.exited) {
this.setState({ exited: false });
}
}
componentDidUpdate(prevProps) {
if (prevProps.open !== this.props.open) {
if (this.props.open) {
this.show();
} else {
clearTimeout(this.timerAutoHide);
}
}
}
componentWillUnmount() {
clearTimeout(this.timerAutoHide);
}
show() {
const toValue = SHOW_HEIGHT;
Animated.timing(this.state.moveHeightAnimated, {
toValue,
duration: 225,
easing: Easing.bezier(0.0, 0.0, 0.2, 1),
}).start(this.setAutoHideTimer);
}
hide() {
const toValue = HIDDEN_HEIGHT;
Animated.timing(this.state.moveHeightAnimated, {
toValue,
duration: 195,
easing: Easing.bezier(0.4, 0.0, 1, 1),
}).start(this.onFinishedHiding);
}
onFinishedHiding = () => {
this.setState({ exited: true });
if (this.props.onRequestClose) {
this.props.onRequestClose();
}
}
setAutoHideTimer = () => {
if (!this.props.onRequestClose) {
return;
}
clearTimeout(this.timerAutoHide);
this.timerAutoHide = setTimeout(() => {
if (!this.props.onRequestClose) {
return;
}
this.hide();
}, this.props.autoHideDuration || DEFAULT_AUTOHIDE_DURATION);
}
render() {
if (!this.props.open && this.state.exited) {
return null;
}
return (
<Animated.View style={[styles.msgContainerStyle, { bottom: this.state.moveHeightAnimated }]} >
<View style={styles.noticeContainerStyle}>
<Text style={styles.msgTextStyle}>{this.props.message}</Text>
</View>
</Animated.View>
);
}
}