I am using react-transition-group in a ReactJS and GatsbyJS (V2) project.
I have my page transitions working with animation but when Link
exit, the exiting
animation is cut short because the next page is ready for entering.
I have tried delaying the Link
action but whilst the page change was delayed, the exit
animation is not triggered until the delay
was over and the Link
was actioned.
How can I delay
the page change, whilst initiating the exiting
animation onClick
? Alternatively, is there a better way or props
available?
Here is my code
Layout.js
class Layout extends React.Component {
...
return (
<Transition>{children}</Transition>
);
}
Transition.js
class Transition extends React.Component {
constructor(props) {
super(props);
this.state = { exiting: false };
this.listenerHandler = this.listenerHandler.bind(this);
}
listenerHandler() {
this.setState({ exiting: true });
}
componentDidMount() {
window.addEventListener(historyExitingEventType, this.listenerHandler);
}
componentWillUnmount() {
window.removeEventListener(historyExitingEventType, this.listenerHandler);
}
static getDerivedStateFromProps({ exiting }) {
if (exiting) {
return { exiting: false };
}
return null;
}
render() {
const transitionProps = {
timeout: {
enter: 0,
exit: timeout
},
appear: true,
in: !this.state.exiting
};
return (
<ReactTransition {...transitionProps}>
{status => (
<div
style={{
...getTransitionStyle({ status, timeout })
}}
>
{this.props.children}
</div>
)}
</ReactTransition>
);
}
}
export default Transition;
gatsby-config.js
import createHistory from 'history/createBrowserHistory';
const timeout = 1500;
const historyExitingEventType = `history::exiting`;
const getUserConfirmation = (pathname, callback) => {
const event = new CustomEvent(historyExitingEventType, {
detail: { pathname }
});
window.dispatchEvent(event);
setTimeout(() => {
callback(true);
}, timeout);
};
let history;
if (typeof document !== 'undefined') {
history = createHistory({ getUserConfirmation });
history.block(location => location.pathname);
}
export const replaceHistory = () => history;
export { historyExitingEventType, timeout };
getTransitionStyle.js
const getTransitionStyles = timeout => {
return {
entering: {
transform: `scale(1.05) translateZ(0)`,
opacity: 0
},
entered: {
transition: `transform 750ms ease, opacity ${timeout}ms ease`,
transitionDelay: `750ms`,
transform: `scale(1) translateZ(0)`,
opacity: 1
},
exiting: {
transition: `transform 750ms ease, opacity ${timeout}ms ease`,
transform: `scale(0.98) translateZ(0)`,
opacity: 0
}
};
};
const getTransitionStyle = ({ timeout, status }) =>
getTransitionStyles(timeout)[status];
export default getTransitionStyle;