Appearance
React 扫盲
js 类属性声明语法
@babel/plugin-proposal-class-properties
js
class Component extends React.Componenet {
// 1、--- 使用 constructor ---
constructor(props) {
// 使用 extends 的 constructor 里在调用父类的构造函数(super)之后,才能使用 this
super(props) // 将 props 传递给 super 是为了在 constructor 中使用 this.prop
this.state = { email: this.props.email }
// this.handleClick = this.handleClick.bind(this)
}
// 事实上 React 在**调用构造函数后**也立即将 props 赋值到了实例上
// 所以即使不使用 super(props) 在 render 中也可访问 this.props
// 2、--- 不使用 constructor ---
state = { email: this.props.email }
handleClick = () => {
console.log('this is:', this)
}
}callback refs, createRef, forwardRef
- createRef
js
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.myRef = React.createRef() // this.myRef.current 访问 DOM
}
render() {
// ref 可用在 HTML元素、class 组件(不能用在函数组件上,因为它没有实例)
return <div ref={this.myRef} />
// this.myRefDom 访问 DOM
// return <div ref={el => this.myRefDom = el} />;
}
}
// --- 得到 Virtual DOM 过程如下(jsx 会被编译成 React.createElement 函数 -> 创建 Virtual DOM)
// 如果 Greeting 是一个函数组件
const result = Greeting(props) // <p>Hello</p> -> jsx -> Virtual DOM -> mounted -> DOM
// 如果 Greeting 是一个类组件
const instance = new Greeting(props)
const result = instance.render() // <p>Hello</p>- callback refs
js
function CustomTextInput(props) {
return (
// 通过接受父组件的回调把内部 DOM 提供给父组件访问
<div>
<input ref={props.inputRef} />
</div>
)
}
class Parent extends React.Component {
render() {
return (
// this.inputElement 访问的是子组件内的 DOM -> 另一种方法访问子组件 DOM -> forwardRef
<CustomTextInput inputRef={(el) => (this.inputElement = el)} />
)
}
}- forwardRef
js
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
))
const ref = React.createRef() // ref.current 访问的是子组件内部 button DOM
;<FancyButton ref={ref}>Click me!</FancyButton>生命周期
16.3+

getDerivedStateFromProps(nextProps, prevState) {}在这里判断 props 然后 return null 或 对象 -> 更新 state(相当于 setState)shouldComponentUpdate(nextProps, nextState) {}确定是否需要更新(应当使用 React.PureComponent 而不是编写此函数)getSnapshotBeforeUpdate(prevProps, prevState) {}在这里获取本次更新前的 DOM 信息(Ref) -> 返回值将作为componentDidUpdate的第三个参数componentDidMountcomponentDidUpdate(prevProps, prevState, snapshot) {}执行副作用操作 hooks ->useEffectcomponentWillUnmount取消网络请求、移除与该组件相关的事件监听、定时器等class 组件编写顺序推荐
constructor(props) {}static属性/方法static propTypesstatic defaultPropsstatic getDerivedStateFromProps(props, state) {}
componentDidMount() {}使用shouldComponentUpdate(nextProps, nextState) {}使用React.PureComponentReact.memo吧getSnapshotBeforeUpdate(prevProps, prevState) {}componentDidUpdate(prevProps, prevState, snapshot) {}componentWillUnmount() {}点击处理程序或事件处理程序,如 onClickSubmit() 或 onChangeDescription()
用于渲染的 getter 方法,如 getSelectReason() 或 getFooterContent()
可选的渲染方法,如 renderNavigation() 或 renderProfilePicture()
render() 除了这个其他都可以不写
其他点
在 JSX 中 含有
.的大写和小写标签名都不会被认为是 HTML 标签空标签
<React.StrictMode><React.StrictMode/><React.Fragment><React.Fragment/><></>指定挂载 DOM
ReactDOM.createPortal静态属性
contextTypepropTypesdefaultPropsdisplayName错误边界包含
static getDerivedStateFromError(error) {}或componentDidCatch(error, info) {}jsx 属性
dangerouslySetInnerHTMLjsfunction createMarkup() { return { __html: '<div>First · Second<div/>' } } function MyComponent() { return <div dangerouslySetInnerHTML={createMarkup()} /> }类 -> 装饰器 -> 高阶函数
组件何时 update
只在 render() 方法中读取
this.props和this.state那么 props state 变化时 组件就会更新如果 render() 方法依赖于其他数据,可以通过调用 forceUpdate() 更新
React.lazy()和dynamic import()Suspensejsconst OtherComponent = React.lazy(() => import('./OtherComponent')) function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> </div> ) }Context API
Provider生产数据static contextType消费数据 - 用于 class 组件this.contextConsumer组件 render props -> 订阅、消费
CRA
- HTTPSjs
"scripts": { "start": "set HTTPS=true && react-scripts start" }
- HTTPS
Hooks
eslint-plugin-react-hooksCRA 默认