Simple react css transitions
MIT License
React-showof is a small (less than 500b) and opiniated component to help with (un)mounting transitions.
Many times in my workflow i just need to show a litle animation when showing and hidding a component.
Css transitions are good for animations based on state change, but the problem is that you might not want to have your component mounted because it may be heavy and the user may not even do the action to show it ever, so its a waste of rendering and DOM nodes.
If you conditionaly mount and apply the transitions it wont work, because you need to have a previous state to transition from.
Mount your component with a idle
state that will represent your initial styles like:
.my-component.idle {
opacity: 0;
}
Then change it right away to the enter
state:
.my-component.enter {
transition: opacity 300ms linear;
opacity: 1;
}
Now, how do you manage this state change, and what to do for unmount?
The solution could to use CSSTransition
from react-transition-group to managed that state changes.
I find it to litle bit over complicated and to have too many states that ends up being hard to understand what to use when.
ShowOf takes care of mounting and unmounting your component and pass the current state of the animation.
<ShowOff
when={shouldShow}
duration={timeToUnmount}
noAppear={avoidAnimateOnMount}
noKeepProps={alwaysPassFreshProps}
render={componentToRender}
/>
when
: boolean, do we ant to show or not our componentduration
: number, how many time do we want to wait until our component unmounts after setting when to falsenoAppear
: if we initially mount with when=true
, do we want to animate the appearence of it?noKeepProps
: when we are unmounting we pass the extra props from last positive render to render
render
: Component or function to render...props
: the rest of the props passed to ShowOf
will be passed to the render
component or functionrender
component/function receives as props:
when
propstate
the current State
onTransitionEnd
to assing to the inner dom component so we can unmount after the animation run...props
plus the rest of the props.Note onTransitionEnd
is only passed when you don't specify duration
State
is composed by 3 states idle
, enter
, exit
:
idle
when the component is mounted, its the begin style where you want to animate from
when mounting.enter
just after rendering idle
state, it is changed to this state, where you set the to
styes and transitions you want to applyexit
is where when
becames false and we start unmounting the component, where you set the to styles for the unmount transition animationExtra props passed to ShowOf
will be passed down to the render
component.
By default when unmounting we keep passing down the last "positive" props, that means the last props before changing when
to false.
Check this example
/* component style */
.test {
border: 1px solid gray;
}
/*
common styles for idle and exit as we use the same transitions
for enter and exit
*/
.test.idle,
.test.exit {
opacity: 0;
width: 20%;
}
/* styles to apply on enter state */
.test.enter {
transition: opacity 300ms linear, width 300ms ease-in;
opacity: 1;
width: 100%;
}
/* styles to apply on exit state */
.test.exit {
transition: opacity 300ms linear, width 300ms ease-out;
}
function Test() {
const [show, setShow] = React.useState(false);
return (
<div>
<button onClick={() => setShow(!show)}>Toggle {show ? 'off' : 'on'}</button>
<ShowOf
when={show}
duration={300}
render={({ state }) => {
return <div className={`test ${state}`}>Hello {state}</div>;
}}
/>
</div>
);
}
To use react-showof
with preact
you can do:
import { ShowOf } from 'react-showof/preact';
Because ShowOf
uses forwardRef
to allow you to pass ref's easy to the inner element, that would mean importing forwardRef
from preact/compat
and that might bring a unexpected behaviour