[文献链接](https://ijpqg5zm8j.feishu.cn/docs/doccnf8zVMcqwwjw6TWz5SnoUmf#hX0qpF
Valid JSX Element
一个 JSX Element 合法的返回类型有:
- ReactElement (
<Component />
) - 数字 (
1
) - 数组 (
[1, <Component />, 'str', null, [11, <Component />, false]]
) - 字符串 (
"string"
) - null (
null
) - false (
false
)
但由于 TS 定义问题,如果我们一个 Component 返回的是数字、数组、字符串、false,不能以 <Component />
方式调用,只能 {Component()}
调用。
Fragment 的作用
如果觉得 {Component()}
这种方式调用很不爽,不整齐,可以考虑用 Fragment 包裹一下。
<Fragment>{1}<Component />{'str'}{null}{[11, <Component />, false]}</Fragment>
这样就能绕过 TS 类型检查的问题。
Fragment 实质上是个特殊渲染片段,相当于以数组的方式包裹一组组件进行渲染。
key 和 ref
React 组件中 props 有两个保留字段,key 和 ref。
key
key 是用来追踪 React Component 和实际渲染的 DOM 节点用的。默认使用组件所在位置进行标记。
在渲染数组数据时,提供 key 可以提升 React 复用 DOM 节点的能力。
index 作为 key 比 id 快一倍
原因是当组件树某位置的 key 跟之前渲染的同位置节点有变更时,react 会认为源组件不可复用,会执行完整的 unmount 步骤,删除包括真实 DOM 节点在内的所有数据,完全重新初始化该节点。这个性能差距会随着节点复杂度成几何级别的增大。所以,不要听信一些最佳实践所谓的要将 id 作为 key 渲染。弄清楚 react 运行的原理,才能做出恰当的选择。
总结一下:
- 当渲染的组件是完全受控的组件时,就应该用 index 作为 key,以最大限度复用已有节点数据。
- 当渲染的组件有内部 state 时,可以通过改变 key,来重置组件内部 state。
ref
ref 一般用来获取 DOM 节点。
react 本质上将 ref 作为 Mutable 对象来看待,通过 ref 可以反向将子组件的内部方法和状态通过 Mutable 的 ref 传递给父组件。
如果是自定义组件,在这里不推荐用 ref,因为写起来麻烦,且容易内存泄漏。
ref 的正确使用方式及副作用回收
ref 作为 React 中唯一的 Mutable 传递方式,形成了一套独特的使用范例。如果传给 ref 的是一个函数,这个函数的调用有以下规则:
- 如果 ref 函数跟上一次的 ref 函数不一致(引用比较),那么会在上一次渲染的 useLayoutEffect / useEffect 的回收函数调用后调用,且调用参数为 null,在本次渲染的 useLayoutEffect / useEffect 的回调函数之前,用 reference 实例调用一次 ref 函数。
- 如果 ref 函数跟上一次的 ref 函数一致,则重绘时不会调用 ref 函数。
受控与非受控的决策
受控组件:
没有内部状态或内部状态完全由 props 决定的组件
非受控组件:
存在不受 props 控制的内部状态的组件
受控组件的优缺点
优点
受控组件由于完全受父组件的传参控制,意味着使用多个受控组件时,可以在父组件自然而然的访问、修改所有组件状态。当有多个受控组件状态通信、联动的时候,父组件可以方便的根据需求更新子组件状态。
缺点
组件状态不闭环,性能差。受控组件所有状态存放在父组件,导致受控组件需要更新 UI 时,需要通过触发父组件的状态更新来更新自身,父组件的更新会触发所有子组件更新。
性能问题常见在 CRUD 列表和复杂表单业务中出现。受控组件即使完全独立于其他兄弟组件,更新时也会触发兄弟组件的重绘。
使用较复杂,因为 props 传参多。不利于父组件分离关注点。
非受控组件优缺点
优点
非受控组件的优缺点正好和受控组件相反。优点是性能好,更新不依赖父组件,从而避免触发兄弟组件更新。由于逻辑高内聚,对父组件传参依赖少,使用也更简单。
缺点
非受控组件的重置和关联更新比较困难、复杂,需要先卸载掉组件再重新初始化,一般使用 key 来解决