Skip to content

Commit a88294b

Browse files
committed
fix: update #3
1 parent 202a5f8 commit a88294b

File tree

1 file changed

+142
-109
lines changed
  • showcase/src/patterns

1 file changed

+142
-109
lines changed

showcase/src/patterns/03.js

Lines changed: 142 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, {
22
useState,
3+
useCallback,
34
useEffect,
5+
useLayoutEffect,
46
useContext,
5-
useMemo,
67
useRef,
8+
useMemo,
79
createContext
810
} from 'react'
911

@@ -13,102 +15,113 @@ import { generateRandomNumber } from '../utils/generateRandomNumber'
1315
import styles from './index.css'
1416

1517
/** ====================================
16-
* 🔰Hook
17-
Hook for Animation
18-
==================================== **/
18+
* 🔰Hook
19+
Hook for Animation
20+
==================================== **/
1921

20-
const useClapAnimation = ({ duration: tlDuration }) => {
22+
const useClapAnimation = ({
23+
duration: tlDuration,
24+
bounceEl,
25+
fadeEl,
26+
burstEl
27+
}) => {
2128
const [animationTimeline, setAnimationTimeline] = useState(
2229
new mojs.Timeline()
2330
)
2431

25-
useEffect(
26-
() => {
27-
const triangleBurst = new mojs.Burst({
28-
parent: '#clap',
29-
radius: { 50: 95 },
30-
count: 5,
31-
angle: 30,
32-
children: {
33-
shape: 'polygon',
34-
radius: { 6: 0 },
35-
scale: 1,
36-
stroke: 'rgba(211,84,0 ,0.5)',
37-
strokeWidth: 2,
38-
angle: 210,
39-
delay: 30,
40-
speed: 0.2,
41-
easing: mojs.easing.bezier(0.1, 1, 0.3, 1),
42-
duration: tlDuration
43-
}
44-
})
45-
46-
const circleBurst = new mojs.Burst({
47-
parent: '#clap',
48-
radius: { 50: 75 },
49-
angle: 25,
50-
duration: tlDuration,
51-
children: {
52-
shape: 'circle',
53-
fill: 'rgba(149,165,166 ,0.5)',
54-
delay: 30,
55-
speed: 0.2,
56-
radius: { 3: 0 },
57-
easing: mojs.easing.bezier(0.1, 1, 0.3, 1)
58-
}
59-
})
60-
61-
const countAnimation = new mojs.Html({
62-
el: '#clapCount',
63-
isShowStart: false,
64-
isShowEnd: true,
65-
y: { 0: -30 },
66-
opacity: { 0: 1 },
32+
useLayoutEffect(() => {
33+
if (!bounceEl || !fadeEl || !burstEl) {
34+
return
35+
}
36+
37+
const triangleBurst = new mojs.Burst({
38+
parent: burstEl,
39+
radius: { 50: 95 },
40+
count: 5,
41+
angle: 30,
42+
children: {
43+
shape: 'polygon',
44+
radius: { 6: 0 },
45+
scale: 1,
46+
stroke: 'rgba(211,84,0 ,0.5)',
47+
strokeWidth: 2,
48+
angle: 210,
49+
delay: 30,
50+
speed: 0.2,
51+
easing: mojs.easing.bezier(0.1, 1, 0.3, 1),
6752
duration: tlDuration
68-
}).then({
69-
opacity: { 1: 0 },
70-
y: -80,
71-
delay: tlDuration / 2
72-
})
73-
74-
const countTotalAnimation = new mojs.Html({
75-
el: '#clapCountTotal',
76-
isShowStart: false,
77-
isShowEnd: true,
78-
opacity: { 0: 1 },
79-
delay: (3 * tlDuration) / 2,
80-
duration: tlDuration,
81-
y: { 0: -3 }
82-
})
83-
84-
const scaleButton = new mojs.Html({
85-
el: '#clap',
86-
duration: tlDuration,
87-
scale: { 1.3: 1 },
88-
easing: mojs.easing.out
89-
})
90-
91-
const clap = document.getElementById('clap')
53+
}
54+
})
55+
56+
const circleBurst = new mojs.Burst({
57+
parent: burstEl,
58+
radius: { 50: 75 },
59+
angle: 25,
60+
duration: tlDuration,
61+
children: {
62+
shape: 'circle',
63+
fill: 'rgba(149,165,166 ,0.5)',
64+
delay: 30,
65+
speed: 0.2,
66+
radius: { 3: 0 },
67+
easing: mojs.easing.bezier(0.1, 1, 0.3, 1)
68+
}
69+
})
70+
71+
const countAnimation = new mojs.Html({
72+
el: bounceEl,
73+
isShowStart: false,
74+
isShowEnd: true,
75+
y: { 0: -30 },
76+
opacity: { 0: 1 },
77+
duration: tlDuration
78+
}).then({
79+
opacity: { 1: 0 },
80+
y: -80,
81+
delay: tlDuration / 2
82+
})
83+
84+
const countTotalAnimation = new mojs.Html({
85+
el: fadeEl,
86+
isShowStart: false,
87+
isShowEnd: true,
88+
opacity: { 0: 1 },
89+
delay: (3 * tlDuration) / 2,
90+
duration: tlDuration,
91+
y: { 0: -3 }
92+
})
93+
94+
const scaleButton = new mojs.Html({
95+
el: burstEl,
96+
duration: tlDuration,
97+
scale: { 1.3: 1 },
98+
easing: mojs.easing.out
99+
})
100+
101+
if (typeof burstEl === 'string') {
92102
clap.style.transform = 'scale(1, 1)'
103+
const el = document.getElementById(id)
104+
el.style.transform = 'scale(1, 1)'
105+
} else {
106+
burstEl.style.transform = 'scale(1, 1)'
107+
}
93108

94-
const updatedAnimationTimeline = animationTimeline.add([
95-
countAnimation,
96-
countTotalAnimation,
97-
scaleButton,
98-
circleBurst,
99-
triangleBurst
100-
])
101-
102-
setAnimationTimeline(updatedAnimationTimeline)
103-
},
104-
[tlDuration, animationTimeline]
105-
)
109+
const updatedAnimationTimeline = animationTimeline.add([
110+
countAnimation,
111+
countTotalAnimation,
112+
scaleButton,
113+
circleBurst,
114+
triangleBurst
115+
])
116+
117+
setAnimationTimeline(updatedAnimationTimeline)
118+
}, [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl])
106119

107120
return animationTimeline
108121
}
109122
/** ====================================
110-
* 🔰 MediumClap
111-
==================================== **/
123+
* 🔰 MediumClap
124+
==================================== **/
112125
const initialState = {
113126
count: 0,
114127
countTotal: generateRandomNumber(500, 10000),
@@ -123,7 +136,24 @@ const MediumClap = ({ children, onClap }) => {
123136
const [clapState, setClapState] = useState(initialState)
124137
const { count, countTotal, isClicked } = clapState
125138

126-
const animationTimeline = useClapAnimation({ duration: 300 })
139+
const [{ clapRef, clapCountRef, clapTotalRef }, setRefState] = useState({})
140+
141+
const setRef = useCallback(node => {
142+
if (node !== null) {
143+
setRefState(prevRefState => ({
144+
...prevRefState,
145+
[node.dataset.refkey]: node
146+
}))
147+
}
148+
}, [])
149+
150+
const animationTimeline = useClapAnimation({
151+
duration: 300,
152+
bounceEl: clapCountRef,
153+
fadeEl: clapTotalRef,
154+
burstEl: clapRef
155+
})
156+
127157
const handleClapClick = () => {
128158
// 👉 prop from HOC
129159
animationTimeline.replay()
@@ -137,38 +167,41 @@ const MediumClap = ({ children, onClap }) => {
137167

138168
const componentJustMounted = useRef(true)
139169

140-
useEffect(
141-
() => {
142-
if (!componentJustMounted.current) {
143-
onClap(clapState)
144-
}
145-
componentJustMounted.current = false
146-
},
147-
[count, onClap]
148-
)
170+
useEffect(() => {
171+
if (!componentJustMounted.current) {
172+
onClap(clapState)
173+
}
174+
componentJustMounted.current = false
175+
}, [count, onClap])
149176

150177
const memoizedValue = useMemo(
151178
() => ({
152179
count,
153180
countTotal,
154-
isClicked
181+
isClicked,
182+
setRef
155183
}),
156-
[count, countTotal, isClicked]
184+
[count, countTotal, isClicked, setRef]
157185
)
158186

159187
return (
160188
<Provider value={memoizedValue}>
161-
<button id='clap' className={styles.clap} onClick={handleClapClick}>
189+
<button
190+
ref={setRef}
191+
data-refkey='clapRef'
192+
className={styles.clap}
193+
onClick={handleClapClick}
194+
>
162195
{children}
163196
</button>
164197
</Provider>
165198
)
166199
}
167200

168201
/** ====================================
169-
* 🔰SubComponents
170-
Smaller Component used by <MediumClap />
171-
==================================== **/
202+
* 🔰SubComponents
203+
Smaller Component used by <MediumClap />
204+
==================================== **/
172205

173206
const ClapIcon = () => {
174207
const { isClicked } = useContext(MediumClapContext)
@@ -187,17 +220,17 @@ const ClapIcon = () => {
187220
)
188221
}
189222
const ClapCount = () => {
190-
const { count } = useContext(MediumClapContext)
223+
const { count, setRef } = useContext(MediumClapContext)
191224
return (
192-
<span id='clapCount' className={styles.count}>
225+
<span ref={setRef} data-refkey='clapCountRef' className={styles.count}>
193226
+{count}
194227
</span>
195228
)
196229
}
197230
const CountTotal = () => {
198-
const { countTotal } = useContext(MediumClapContext)
231+
const { countTotal, setRef } = useContext(MediumClapContext)
199232
return (
200-
<span id='clapCountTotal' className={styles.total}>
233+
<span ref={setRef} data-refkey='clapTotalRef' className={styles.total}>
201234
{countTotal}
202235
</span>
203236
)
@@ -218,10 +251,10 @@ MediumClap.Total = CountTotal
218251
MediumClap.Info = ClapInfo
219252

220253
/** ====================================
221-
* 🔰USAGE
222-
Below's how a potential user
223-
may consume the component API
224-
==================================== **/
254+
* 🔰USAGE
255+
Below's how a potential user
256+
may consume the component API
257+
==================================== **/
225258

226259
const Usage = () => {
227260
const [total, setTotal] = useState(0)

0 commit comments

Comments
 (0)