Skip to content

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 的第三个参数

  • componentDidMount componentDidUpdate(prevProps, prevState, snapshot) {} 执行副作用操作 hooks -> useEffect

  • componentWillUnmount 取消网络请求、移除与该组件相关的事件监听、定时器等

  • class 组件编写顺序推荐

    • constructor(props) {}

    • static 属性/方法

      • static propTypes

      • static defaultProps

      • static getDerivedStateFromProps(props, state) {}

    • componentDidMount() {}

    • shouldComponentUpdate(nextProps, nextState) {} 使用 React.PureComponent 使用 React.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

  • 静态属性 contextType propTypes defaultProps displayName

  • 错误边界包含 static getDerivedStateFromError(error) {}componentDidCatch(error, info) {}

  • jsx 属性 dangerouslySetInnerHTML

    js
    function createMarkup() {
      return { __html: '<div>First &middot; Second<div/>' }
    }
    
    function MyComponent() {
      return <div dangerouslySetInnerHTML={createMarkup()} />
    }
  • 类 -> 装饰器 -> 高阶函数

  • 组件何时 update

    • 只在 render() 方法中读取 this.propsthis.state 那么 props state 变化时 组件就会更新

    • 如果 render() 方法依赖于其他数据,可以通过调用 forceUpdate() 更新

  • React.lazy()dynamic import() Suspense

    js
    const OtherComponent = React.lazy(() => import('./OtherComponent'))
    
    function MyComponent() {
      return (
        <div>
          <Suspense fallback={<div>Loading...</div>}>
            <OtherComponent />
          </Suspense>
        </div>
      )
    }
  • Context API

    • Provider 生产数据
    • static contextType 消费数据 - 用于 class 组件 this.context
    • Consumer 组件 render props -> 订阅、消费
  • CRA

    • HTTPS
      js
      "scripts": {
        "start": "set HTTPS=true && react-scripts start"
      }
  • Hooks

    • eslint-plugin-react-hooks CRA 默认