关于 React 的一些小知识
这里搜集了几个关于 react 的零散知识,有些虽然知道了也不一定能帮你写出更好的代码,但能够扩展一下知识。
以下全部来自于 https://overreacted.io,需要更详细解释的可以去里面找相关文章。
1. 关于 lint
eslint 有一条规则是不允许在 componentDidMount 中 setState,但实际上确实有一种情况需要这么做:计算出渲染好的 DOM 尺寸然后执行后续操作。如果某种行为是需要被限制的,那么通常来说 react 一定会警告你或者拒绝执行:例如组件卸载后执行 setState。
所以 lint 并非是完美的开发规范,当然它能够规范团队的代码并且显著的帮你降低 bug 的出现,但是你需要知道你的代码被标红是为什么,该条规则是否是绝对正确的并且能降低 bug?如果不是,你完全可以把它去掉。
2. $$typeof: Symbol(react.element)
如果你把一个组件实例打印出来,你会发现除了我们熟悉的 props children ref 等属性,还有一个
$$typeof: Symbol(react.element)
那么这个 $$typeof 是干嘛的呢?实际上是用于安全方面的。
假设你的站点不安全,然后使得用户可以存储 json 格式的数据,那么当你输出数据时这段 json 可能会被处理为对象,如果这个对象符合 React Element 的定义就会形成 xss 攻击。
所以在 react 0.14 之后,react 在每个 React Element 上都附上了这个 $$typeof: Symbol(react.element)属性,由于 Symbol 不能在 json 中进行传输所以没有办法用这种方式伪造 React Element。
浏览器不支持 Symbol 怎么办?那就没办法获得这种保护了,这种情况下 react 为了一致性考虑会将 $$typeof 设置为一个数字:0xeac7(0xeac7 看起来像 react)。
3. react 怎么知道你的组件是函数组件还是类组件?
如果一个组件是函数组件,那么可以直接用 Page({title: ‘hello’})来创建,但是如果是类组件那么就需要用 new 操作符来实例化,那么 react 是怎么区分这两种组件的呢?
首先,直接判断是函数还是类是很困难的,即使你能够 tell a class from a function in JavaScript,被 babel 转译后就行不通了,因为类也会被转译为函数。
下面直接出结论:由于当你写组件时一定是 extends React.Component 的形式,所以只要在 Component 上定义一个特殊字段表示这是类组件就可以了。不能是类的静态属性,因为有些转码器不能正确复制静态属性,所以需要设置为实例属性,也就是 Component.prototype.isReactComponent = {};。
isReactComponent 被设置为 {} 而不是 true 是由于早期的 Jest 会在某些情况下删除基本类型的属性。用 Page.prototype instanceof React.Component 来判断行不行?不太行,因为有可能你的项目中有两个 react 包,不管是不是故意的。
4. super(props)到底要不要传入 props
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = {isOn: true};
}
// …
}
简单来说,即使你不传 props,react 也会在组件实例化后自动把 props 挂载上去,这也是为什么你不传 props 但是你依然能在组件内其他地方使用 this.props 的原因:
// Inside React
const instance = new YourComponent(props);
instance.props = props;
但是这种情况你不能在 constructor 内使用 this.props,因为 props 只有在实例化之后才会被挂载到实例上面。那如果你希望在 constructor 内使用,你就需要将 props 传入 super():
class Checkbox extends React.Component {
constructor(props) {
super(props);
console.log(this.props);
}
// …
}
// 当执行 super 的时候
class Component {
constructor(props) {
this.props = props;
// …
}
}
但是为什么能够在下面这种形式下使用 this.props:
class Checkbox extends React.Component {
state = {isOn: this.props.isOn};
// …
}
因为 @babel/plugin-proposal-class-properties 帮你提供了正确传递参数的默认 constructor,否则你也不能使用这种写法。
参考:Writing Resilient ComponentsWhy Do React Elements Have a $$typeof Property?How Does React Tell a Class from a Function?Why Do We Write super(props)?