Skip to content

Commit feeb58b

Browse files
authored
fix: useTrail should not run on initial render when a ref is passed (pmndrs#2026)
1 parent ba29d5d commit feeb58b

File tree

15 files changed

+303
-123
lines changed

15 files changed

+303
-123
lines changed

.changeset/mighty-mails-float.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@react-spring/core': patch
3+
'@react-spring/animated': patch
4+
'@react-spring/parallax': patch
5+
'@react-spring/rafz': patch
6+
'react-spring': patch
7+
'@react-spring/shared': patch
8+
'@react-spring/types': patch
9+
'@react-spring/konva': patch
10+
'@react-spring/native': patch
11+
'@react-spring/three': patch
12+
'@react-spring/web': patch
13+
'@react-spring/zdog': patch
14+
---
15+
16+
fix: useTrail ref bug

.codesandbox/ci.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"/demo/src/sandboxes/chain",
88
"/demo/src/sandboxes/css-gradients",
99
"/demo/src/sandboxes/css-keyframes",
10+
"/demo/src/sandboxes/css-variables",
1011
"/demo/src/sandboxes/draggable-list",
1112
"/demo/src/sandboxes/exit-before-enter",
1213
"/demo/src/sandboxes/flip-card",
@@ -23,6 +24,7 @@
2324
"/demo/src/sandboxes/rocket-decay",
2425
"/demo/src/sandboxes/simple-transition",
2526
"/demo/src/sandboxes/slide",
27+
"/demo/src/sandboxes/smile-grid",
2628
"/demo/src/sandboxes/springy-boxes",
2729
"/demo/src/sandboxes/svg-filter",
2830
"/demo/src/sandboxes/trail",

demo/src/App.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import SimpleTransition from './sandboxes/simple-transition/src/App'
3939
import Slide from './sandboxes/slide/src/App'
4040
import SvgFilter from './sandboxes/svg-filter/src/App'
4141
import SpringBoxes from './sandboxes/springy-boxes/src/App'
42+
import SmileGrid from './sandboxes/smile-grid/src/App'
4243

4344
import Trail from './sandboxes/trail/src/App'
4445
import Tree from './sandboxes/tree/src/App'
@@ -74,6 +75,7 @@ const links = {
7475
'parallax-sticky': ParallaxSticky,
7576
'simple-transition': SimpleTransition,
7677
slide: Slide,
78+
'smile-grid': SmileGrid,
7779
'spring-boxes': SpringBoxes,
7880
'svg-filter': SvgFilter,
7981
trail: Trail,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"arrowParens": "avoid",
3+
"jsxBracketSameLine": true,
4+
"printWidth": 120,
5+
"semi": false,
6+
"singleQuote": true,
7+
"tabWidth": 2,
8+
"trailingComma": "es5"
9+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "Smile Grid",
3+
"description": "An animated SVG grid with a smiley face inside!",
4+
"keywords": [
5+
"useTrail",
6+
"useChain",
7+
"useSprings",
8+
"useSpringRef",
9+
"svg"
10+
],
11+
"version": "1.0.0",
12+
"main": "src/index.tsx",
13+
"dependencies": {
14+
"@react-spring/web": "9.5.5",
15+
"react": "18.2.0",
16+
"react-dom": "18.2.0",
17+
"react-scripts": "5.0.1"
18+
},
19+
"scripts": {
20+
"start": "react-scripts start",
21+
"build": "react-scripts build",
22+
"test": "react-scripts test --env=jsdom",
23+
"eject": "react-scripts eject"
24+
},
25+
"browserslist": [
26+
">0.2%",
27+
"not dead",
28+
"not ie <= 11",
29+
"not op_mini all"
30+
],
31+
"devDependencies": {
32+
"@types/react": "^18.0.8",
33+
"@types/react-dom": "^18.0.3",
34+
"typescript": "^4.8.3"
35+
}
36+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
6+
<meta name="theme-color" content="#000000" />
7+
<!--
8+
manifest.json provides metadata used when your web app is added to the
9+
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
10+
-->
11+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
12+
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
13+
<!--
14+
Notice the use of %PUBLIC_URL% in the tags above.
15+
It will be replaced with the URL of the `public` folder during the build.
16+
Only files inside the `public` folder can be referenced from the HTML.
17+
18+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
19+
work correctly both with client-side routing and a non-root public URL.
20+
Learn how to configure a non-root public URL by running `npm run build`.
21+
-->
22+
<title>React Spring Sandbox</title>
23+
</head>
24+
25+
<body>
26+
<noscript> You need to enable JavaScript to run this app. </noscript>
27+
<div id="root"></div>
28+
<!--
29+
This HTML file is a template.
30+
If you open it directly in the browser, you will see an empty page.
31+
32+
You can add webfonts, meta tags, or analytics to this file.
33+
The build step will place the bundled scripts into the <body> tag.
34+
35+
To begin the development, run `npm start` or `yarn start`.
36+
To create a production bundle, use `npm run build` or `yarn build`.
37+
-->
38+
</body>
39+
</html>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import * as React from 'react'
2+
import { useTrail, useChain, useSprings, animated, useSpringRef } from '@react-spring/web'
3+
4+
import styles from './styles.module.css'
5+
6+
const COORDS = [
7+
[50, 30],
8+
[90, 30],
9+
[50, 50],
10+
[60, 60],
11+
[70, 60],
12+
[80, 60],
13+
[90, 50],
14+
]
15+
16+
const STROKE_WIDTH = 0.5
17+
18+
const OFFSET = STROKE_WIDTH / 2
19+
20+
const MAX_WIDTH = 150 + OFFSET * 2
21+
const MAX_HEIGHT = 100 + OFFSET * 2
22+
23+
export default function App() {
24+
const gridApi = useSpringRef()
25+
26+
const gridSprings = useTrail(16, {
27+
ref: gridApi,
28+
from: {
29+
x2: 0,
30+
y2: 0,
31+
},
32+
to: {
33+
x2: MAX_WIDTH,
34+
y2: MAX_HEIGHT,
35+
},
36+
})
37+
38+
const boxApi = useSpringRef()
39+
40+
const [boxSprings] = useSprings(7, i => ({
41+
ref: boxApi,
42+
from: {
43+
scale: 0,
44+
},
45+
to: {
46+
scale: 1,
47+
},
48+
delay: i * 200,
49+
config: {
50+
mass: 2,
51+
tension: 220,
52+
},
53+
}))
54+
55+
useChain([gridApi, boxApi], [0, 1], 1500)
56+
57+
return (
58+
<div className={styles['background-container']}>
59+
<div className={styles.container}>
60+
<svg viewBox={`0 0 ${MAX_WIDTH} ${MAX_HEIGHT}`}>
61+
<g>
62+
{gridSprings.map(({ x2 }, index) => (
63+
<animated.line
64+
x1={0}
65+
y1={index * 10 + OFFSET}
66+
x2={x2}
67+
y2={index * 10 + OFFSET}
68+
key={index}
69+
strokeWidth={STROKE_WIDTH}
70+
stroke="currentColor"
71+
/>
72+
))}
73+
{gridSprings.map(({ y2 }, index) => (
74+
<animated.line
75+
x1={index * 10 + OFFSET}
76+
y1={0}
77+
x2={index * 10 + OFFSET}
78+
y2={y2}
79+
key={index}
80+
strokeWidth={STROKE_WIDTH}
81+
stroke="currentColor"
82+
/>
83+
))}
84+
</g>
85+
{boxSprings.map(({ scale }, index) => (
86+
<animated.rect
87+
key={index}
88+
width={10}
89+
height={10}
90+
fill="currentColor"
91+
style={{
92+
transformOrigin: `${5 + OFFSET * 2}px ${5 + OFFSET * 2}px`,
93+
transform: `translate(${COORDS[index][0] + OFFSET}px, ${COORDS[index][1] + OFFSET}px)`,
94+
scale,
95+
}}
96+
/>
97+
))}
98+
</svg>
99+
</div>
100+
</div>
101+
)
102+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
html,
2+
body,
3+
#root {
4+
height: 100%;
5+
width: 100%;
6+
}
7+
8+
body {
9+
font-family: system-ui;
10+
margin: 0;
11+
}
12+
13+
*,
14+
*:after,
15+
*:before {
16+
box-sizing: border-box;
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as React from 'react'
2+
import { createRoot } from 'react-dom/client'
3+
import App from './App'
4+
import './index.css'
5+
6+
const rootElement = document.getElementById('root')!
7+
createRoot(rootElement).render(
8+
<React.StrictMode>
9+
<App />
10+
</React.StrictMode>
11+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.background-container {
2+
width: 100%;
3+
height: 100%;
4+
background-color: rgb(0, 0, 255);
5+
color: rgb(255, 255, 255);
6+
display: flex;
7+
justify-content: center;
8+
align-items: center;
9+
}
10+
11+
.container {
12+
max-width: 800px;
13+
width: 50vw;
14+
margin: 0 auto;
15+
}

0 commit comments

Comments
 (0)