--- title: Button with ripple effect tags: components,state,effect expertise: intermediate author: chalarangelo firstSeen: 2019-09-10T09:07:29+03:00 lastUpdated: 2021-10-13T19:29:39+02:00 --- Renders a button that animates a ripple effect when clicked. - Use the `useState()` hook to create the `coords` and `isRippling` state variables. These are used for the pointer's coordinates and the animation state of the button respectively. - Use a `useEffect()` hook to change the value of `isRippling` every time the `coords` state variable changes, starting the animation. - Use `setTimeout()` in the previous hook to clear the animation after it's done playing. - Use a `useEffect()` hook to reset `coords` whenever the `isRippling` state variable is `false`. - Handle the `onClick` event by updating the `coords` state variable and calling the passed callback. ```css .ripple-button { border-radius: 4px; border: none; margin: 8px; padding: 14px 24px; background: #1976d2; color: #fff; overflow: hidden; position: relative; cursor: pointer; } .ripple-button > .ripple { width: 20px; height: 20px; position: absolute; background: #63a4ff; display: block; content: ""; border-radius: 9999px; opacity: 1; animation: 0.9s ease 1 forwards ripple-effect; } @keyframes ripple-effect { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(10); opacity: 0.375; } 100% { transform: scale(35); opacity: 0; } } .ripple-button > .content { position: relative; z-index: 2; } ``` ```jsx const RippleButton = ({ children, onClick }) => { const [coords, setCoords] = React.useState({ x: -1, y: -1 }); const [isRippling, setIsRippling] = React.useState(false); React.useEffect(() => { if (coords.x !== -1 && coords.y !== -1) { setIsRippling(true); setTimeout(() => setIsRippling(false), 300); } else setIsRippling(false); }, [coords]); React.useEffect(() => { if (!isRippling) setCoords({ x: -1, y: -1 }); }, [isRippling]); return ( ); }; ``` ```jsx ReactDOM.render( console.log(e)}>Click me, document.getElementById('root') ); ```