Created
August 10, 2019 19:35
-
-
Save ajsmth/23427981a213e8d193e18ddfd0dc1ccd to your computer and use it in GitHub Desktop.
Pager with Spring Transitions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect } from 'react' | |
import { useSpring, animated, interpolate } from 'react-spring' | |
// let's add some transitions to the pager component when the activeIndex changes | |
function Pager({ children, activeIndex }) { | |
const offset = activeIndex * 100 * -1 | |
// translateX will now represent a spring value that we will animate | |
// we'll set the initial value to our first offset here: | |
const [{ translateX }, set] = useSpring(() => ({ | |
translateX: offset, | |
})) | |
// when the offset updates, we want to update the translateX value | |
// so that the spring will fire again: | |
useEffect(() => { | |
set({ translateX: offset }) | |
}, [offset, set]) | |
// update the container view to an animated.div | |
// we'll use the interpolate() function to translate with our spring values | |
// this gives us a nice spring animation to our page transitions | |
return ( | |
<animated.div | |
style={{ | |
border: 'thin solid blue', | |
position: 'relative', | |
height: '100%', | |
width: '100%', | |
transform: interpolate( | |
[translateX], | |
(translateX) => `translateX(${translateX}%)`, | |
), | |
}}> | |
{React.Children.map(children, (element, index) => { | |
return ( | |
<div | |
style={{ | |
...absoluteFill, | |
transform: `translateX(${index * 100}%)`, | |
}}> | |
{element} | |
</div> | |
) | |
})} | |
</animated.div> | |
) | |
} | |
const absoluteFill = { | |
position: 'absolute', | |
left: 0, | |
right: 0, | |
bottom: 0, | |
top: 0, | |
} | |
const PAGE_SIZE = 200 | |
// this will represent a consumer component or any part of your application | |
function App() { | |
// all we need to pass are children and an activeIndex prop to our pager component | |
const [activeIndex, setActiveIndex] = useState(0) | |
const children = Array.from({ length: 10 }).map((c, i) => ( | |
<h1 key={i} style={{ textAlign: 'center' }}> | |
Index {i} | |
</h1> | |
)) | |
return ( | |
<div> | |
<div | |
style={{ | |
width: PAGE_SIZE, | |
height: PAGE_SIZE, | |
display: 'flex', | |
margin: 'auto', | |
padding: '5px', | |
border: 'thin solid red', | |
}}> | |
<Pager activeIndex={activeIndex}>{children}</Pager> | |
</div> | |
<div | |
style={{ | |
display: 'flex', | |
flexDirection: 'column', | |
alignItems: 'center', | |
justifyContent: 'space-around', | |
}}> | |
<strong style={{ margin: '5px 0' }}>activeIndex: {activeIndex}</strong> | |
<button | |
style={{ margin: '5px 0' }} | |
onClick={() => setActiveIndex(activeIndex + 1)}> | |
Increment | |
</button> | |
<button | |
style={{ margin: '5px 0' }} | |
onClick={() => setActiveIndex(activeIndex - 1)}> | |
Decrement | |
</button> | |
</div> | |
</div> | |
) | |
} | |
export default App |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment