Live Note

Remain optimistic

parseInt 中塞 number

1
2
parseInt(0.000001) // 0
parseInt(0.0000001) // 1

为什么会得到这样的结果?

  1. parseInt(arg: string):接收的是一个string变量。
  2. 0.0000001转成string会变为1e-7
  3. parseInt('1e-7')结果为1

所以要截取小数,最好还是使用Math.trunc(n)

1
2
3
4
5
6
7
8
9
10
const enum Foo {
AA = "aa",
BB = "bb",
}

type B = keyof typeof Foo // 'AA' | 'BB'

// Template Literal Types
type C = `${keyof { [x in Foo]: string }}`
// 'aa' | 'bb'

缘由

公司的 PC 没有音卡。导致耳机不能播放。

使用 pavucontrol 输出为模拟信号

刚开始总报找不到这个 package。
换了官方源也没用。
后来才发现需要打开开源 package 安装。。。software & updates > ubuntu software > open-source software

天下无不散的宴席

实习生只剩下一个了,其他都离职了。对他们来说是件好事,呆在这里也不能提高多少。

最近发生的事情太多了:

  • 养了一只猫:某天突然就想养只猫了,下午决定晚上就去领了一只。回家后花了不少精力,现在活得还算不错。
  • 新买了个镜头:入了个 35mm f2.0 镜头,扫街+人像应该够了。
  • 不知不觉喜欢上了一个女生:深入了解后发现希望不大,还是放弃了。
  • 去了家公司参观:这家公司有 Node 中间层,是以前未接触过的。今后还需努力。
  • 刷了一点 leetcode:在公司需求不多,就刷着为以后做准备了。
  • 买了一点书:身体和心灵总有一个在路上。
  • 去桂山岛旅游:看了看人烟稀少的小镇是什么样的生活。

币圈疯狂的人们

数字货币的世界,涨跌不需要理由。
公司一群人炒币,只有一个人脱身,其余的加起来估计亏了百来万。
地铁上,公交上,餐厅奶茶店;俊男靓女,大爷大妈,所有人都在炒币,太疯狂了。

人的欲望总是无穷的,赌徒只需要输一次就能将所有的钱输完,人性的弱点。
大家都希望山底买,山顶卖。但是谁又知道你是不是买在山顶呢。大家都信仰最大傻瓜理论,觉得自己不是那个大傻瓜。

安心生活

周末出去走走看看世界
看一场电影
看几本书
与朋友游戏几局
平安喜乐就够了

还是决定关闭 blog 了。

太多黑历史,何况还有骂 GCD 的东西。

Null-aware operators

1
2
3
4
5
6
7
8
9
10
String foo = 'a string';
String bar; // Unassigned objects are null by default.

// Substitute an operator that makes 'a string' be assigned to baz.
String baz = foo ?? bar;

void updateSomeVars() {
// Substitute an operator that makes 'a string' be assigned to bar.
bar ??= 'a string';
}

Conditional property access

myObject?.someProperty equals to (myObject != null) ? myObject.someProperty : null.

1
2
3
4
5
6
// This method should return the uppercase version of `str`
// or null if `str` is null.
String upperCaseIt(String str) {
// Try conditionally accessing the `toUpperCase` method here.
return str?.toUpperCase();
}

Cascades

myObject.someMethod() will get the return value of the someMethod(), myObject..someMethod() will get the reference of the myObject.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class BigObject {
int anInt = 0;
String aString = '';
List<double> aList = [];
bool _done = false;

void allDone() {
_done = true;
}
}

BigObject fillBigObject(BigObject obj) {
// Create a single statement that will update and return obj:
return obj
..anInt = 1
..aString = "String!"
..aList = [3.0]
..allDone();
}
Read more »

useMemo

useMemo 是拿来保持一个对象引用不变的。useMemo 和 useCallback 都是 React 提供来做性能优化的。比起 classes, Hooks 给了开发者更高的灵活度和自由,但是对开发者要求也更高了,因为 Hooks 使用不恰当很容易导致性能问题。

假设有个 component,在 dataConfig 变化的时候重新去 fetchData:

1
2
3
4
5
6
<Child
fetchData={() => {
// fetch data
}}
dataConfig={{ id: getId(queryId) }}
/>

如果是个 Class Component,会这么写:

1
2
3
4
5
6
7
class Child extends React.Component<Props> {
componentWillReceiveProps(nextProps: Props) {
if (nextProps.dataConfig !== this.props.dataConfig) {
nextProps.fetchData(nextProps.dataConfig)
}
}
}

使用 Hooks 后长这样:

1
2
3
4
5
const Child = ({ fetchData, dataConfig }: Props) => {
useEffect(() => {
fetchData(dataConfig)
}, [fetchData, dataConfig])
}

使用 Class Component 时我们需要手动管理依赖,但是使用 Hooks 时会带来副作用:React 使用的是Object.is(),如果fetchData的 reference 变了,也会触发 useEffect
虽然逻辑上 React 的处理是合理的,但是还是需要手动去解决它导致的性能问题:官方提供了 useCallback 这个 hooks,用于解决函数引用问题。

Read more »

useRef

  • mutable ref
  • presist

eg: 实现一个需求:点击按钮时 input 自动聚焦。

  • createRef 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const HomePage = () => {
const input = createRef<HTMLInputElement>()

const handle = () => {
if (input.current) {
input.current.focus()
}
}

return (
<div>
<input ref={input} />
<button onClick={handle}>focus</button>
</div>
)
}
  • useRef 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const HomePage = () => {
const input = useRef<HTMLInputElement | null>(null)

const handle = () => {
if (input.current) {
input.current.focus()
}
}

return (
<div>
<input ref={input} />
<button onClick={handle}>focus</button>
</div>
)
}

两者的区别在于:createRef 每次渲染会返回一个新的引用,而 useRef 返回的是相同的引用(persist)。对于函数式组件,每次 useState 会造成整个组件的重新渲染,但是 uesRef 可以保证引用不变,不会触发 re-render。

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 »