Live Note

Remain optimistic

示例

certificate

main.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import Svg, {
Rect,
Text as SvgText,
Path,
LinearGradient as SvgLinearGradient,
Stop,
Defs,
Line,
} from "react-native-svg";
import BuildingSvg from "./BuildingSvg";
<Svg height="500" style={{ marginHorizontal: 16 }} width={wp(100) - 16 * 2}>
<Defs>
<SvgLinearGradient id="textGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<Stop offset="0%" stopColor="#835927" />
<Stop offset="50%" stopColor="#C08035" />
<Stop offset="100%" stopColor="#835927" />
</SvgLinearGradient>
</Defs>
<BuildingSvg />

<Rect
x="10"
y="10"
width="95%"
height="95%"
stroke="#DAA520"
strokeWidth="5"
fill="none"
rx="10"
ry="10"
/>
<Path
d="M20,40 L360,40 M20,460 L360,460 M40,20 L40,480 M340,20 L340,480"
stroke="#DAA520"
strokeWidth="2"
/>
<SvgText
x="50%"
y="80"
fontSize="20"
fontWeight="bold"
textAnchor="middle"
fill="url(#textGradient)"
>
Certificate of Honor
</SvgText>
<SvgText x="50%" y="120" fontSize="16" textAnchor="middle" fill="#835927">
Proudly Persented to
</SvgText>
<SvgText
x="50%"
y="180"
fontSize="24"
fontWeight="bold"
textAnchor="middle"
fill="#835927"
>
Edward
</SvgText>
<Line x1="35%" y1="184" x2="65%" y2="184" stroke="#835927" strokeWidth="2" />
<SvgText x="50%" y="250" fontSize="18" textAnchor="middle" fill="#835927">
We acknowledge your dedication
</SvgText>
<SvgText x="50%" y="270" fontSize="18" textAnchor="middle" fill="#835927">
and applaud your success as
</SvgText>
<SvgText x="50%" y="290" fontSize="18" textAnchor="middle" fill="#835927">
a distinguished trader
</SvgText>
<SvgText x="50%" y="310" fontSize="18" textAnchor="middle" fill="#835927">
in the cryptocurrency market.
</SvgText>
<SvgText
x="50%"
y="450"
fontSize="16"
textAnchor="middle"
fill="url(#textGradient)"
>
NO. 10020123
</SvgText>
</Svg>;
Read more »

Custom Scroll Indicator for ScrollView

Demo.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import React, { useMemo, useState } from "react"
import { ScrollView, View } from "react-native"

const Demo: React.FC = () => {
const [contentSize, setContentSize] = useState(0)
const [scrollViewSize, setScrollViewSize] = useState(0)
const [scrollPosition, setScrollPosition] = useState(0)

const indicatorWidth = useMemo(() => {
if (contentSize > 0 && scrollViewSize > 0) {
return (scrollViewSize / contentSize) * scrollViewSize
}

return 0
}, [contentSize, scrollViewSize])

const indicatorPosition = useMemo(() => {
if (contentSize > 0 && scrollPosition > 0) {
return (scrollPosition / contentSize) * scrollViewSize
}

return 0
}, [contentSize, scrollPosition, scrollViewSize])

return (
<View>
<ScrollView
// disable default scroll indicator
showsHorizontalScrollIndicator={false}
onLayout={(event) => {
setScrollViewSize(event.nativeEvent?.layout?.width ?? 0)
}}
onContentSizeChange={(w) => {
setContentSize(w)
}}
horizontal // set horizontal scroll
scrollEventThrottle={16} // throttle scroll event to improve performance
onScroll={(event) => {
// change scroll position here
const { contentOffset } = event.nativeEvent

const { x = 0 } = contentOffset
const max = contentSize - scrollViewSize
const min = 0

if (x > max) {
setScrollPosition(max)
} else if (x < min) {
setScrollPosition(min)
} else {
setScrollPosition(x)
}
}}
>
{/* Content here */}
</ScrollView>

{/* custom scroll indicator */}
<View
style={{
bottom: 0,
height: 4,
width: indicatorWidth,
position: "absolute",
left: indicatorPosition,
borderRadius: 4,
backgroundColor: "#EEEEEE",
}}
/>
</View>
)
}

export default Demo

基本用法

Set 类似于数组,但是成员的值都是唯一的,没有重复。Set 本身是一个构造函数。

1
2
3
4
5
6
7
8
9
10
11
const set = new Set()
;[1, 2, 3, 4].forEach((x) => set.add(x))
for (let value of set) {
console.log(value) //1, 2, 3, 4
}

const set = new Set([1, 2, 3, 4])
;[...set] //[1, 2, 3, 4]

//数组除重
;[...new Set(array)]

在 Set 内部,NaN 是相等的,两个对象总是不相等的。

1
2
3
4
5
6
7
8
let set = new Set()
let a = NaN
let b = NaN
set.add(a).add(b)
set.size //1

set.add({}).add({})
set.size //3
Read more »

TV series

  • Game of Thrones
  • WestWorld
  • Chernobyl
  • Fantasmagorias
  • Love, Death & Robots
Read more »

友好的 React Hooks

网络上对 react hooks 的评价负面大于正面,确实很容易写出性能有问题的代码,关键就在于:我们太喜欢用 useState 了。
在 vue-composition-api 中,reactivity 数据都有 wrapper,custom-vca 里不管产生多少个 reactivity 对象,不会直接产生 re-render。只有那些被 return 到外部跟 template 绑定的部分才会触发视图渲染。
而 react 的 reactivity 就是通过 re-render 实现的,useState 没有 wrapper,每次使用都会得到一个触发渲染的函数。在这种 reactivity 机制下,就需要特殊的方式编写 hooks —— State/Effect 分层

假设有个 useHeight:

1
const [ref, height] = useHeight()

高度变化时,被动 re-render,难以转换合并。大部分情况下,不提供 state,而提供 effect 可能会更好:

1
2
3
4
5
const [height, setHeight] = useState(0)
const ref = useHeight((height: number) => {
// do something
setHeight(height)
})

使用者在外部声明 state,然后在 callback 中按需 setState。使用者可以结合其他 state,做 dispatch 到 reducer 的一次整体更新,而不是被动 re-render。
根据 State/Effect 分层理念,尝试着给出友好地 react hooks 公式:

1
const handler = useProducer(consumer, options)

producer 接收 consumer callback 作为参数,返回 handler 控制函数,用于绑定到事件或其他位置。

Read more »