「React」class 组件真难用!

825 阅读2分钟

本篇博客用来记录我的学习成果
防止遗忘

ES6 创建 class 组件的方式

import React from 'react'

class App extends React.Component {
  constructor() {
    super()
    this.state = { n: 0 }
  }
  render() {
    return (
      <div>n: {this.state.n}</div>
    )
  }
}

export default App

props

我将它翻译为「外部数据」,更便于理解

props 的作用

  • 接受外部数据

    • 只能读不能写
    • 外部数据由父组件传递
  • 接受外部函数

    • 在恰当的时候,调用该函数
    • 该函数一般是父组件的函数

初始化

class A extends React.Component {
  constructor(props) {
    super(props)
  }
  render(){}
}

这样做之后,this.props 就是外部数据 对象的地址

怎么读

// 通过 this.props.xxx 来读
this.props.xxx

语法

class A extends React.Component {
  constructor(props) {
    super(props)
  }
  render(){
    return <div onClick={this.props.onClick}>
      {this.props.name}
      <div>
        {this.props.children}
      </div>
    </div>
  }
}

示例

class A extends React.Component {
  constructor(props) {
    super(props)
    this.state = { x: 1 }
  }

  onClick = () => {
    this.setState({
      x: this.state.x + 1
    })
  }

  render() {
    return (
      <div>
        这是 A
        <button onClick={this.onClick}>+1</button>
        <B name={this.state.x} />
      </div>
    )
  }
}

class B extends React.Component {
  render() {
    return (
      // 使用 this.props.name 来读
      <div>n: {this.props.name}</div> 
    )
  }
}

怎么写

  • 永远不要去改 props
  • 外部数据,就应该由外部更新
  • 这是 React 的理念!

「state & setState」

我将 state 翻译为「内部数据」

初始化

class A extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      user: {
        name: 'heycn',
        age: 18
      }
    }
  }

  render() {
    return ( ... )
  }
}

怎么读

// 通过 this.state.xxx 来读
this.state.xxx

怎么写

// 通过 this.setState(???, fn) 来写
this.setState(???, fn)

参考这篇博客:「React」牛x的前端这么写 setState()

推荐第二种方法

方法一

重点看 onClick1 的代码

class A extends React.Component {
  constructor(props) {
    super(props)
    this.state = { x: 1 }
  }

  onClick1 = () => {
    this.setState({ x: this.state.x + 1 })
  }

  render() {
    return (
      <div>
        x: {this.state.x}
        <button onClick={this.onClick1}>+1</button>
      </div>
    )
  }
}

方法二

重点看 onClick2 的代码

class A extends React.Component {
  constructor(props) {
    super(props)
    this.state = { x: 1 }
  }

  onClick2 = () => {
    this.setState(state => ({ x: state.x + 1 }))
  }

  render() {
    return (
      <div>
        x: {this.state.x}
        <button onClick={this.onClick2}>+1</button>
      </div>
    )
  }
}

总结

  • 读用 this.state

    • this.state.xxx.yyy.zzz
  • 写用 this.setState(???, fn)

    • this.setState(newState, fn)
    • 注意:setState 不会立刻改变 this.state,会在当前代码运行之后,再去更新 this.state,从而触发 UI 更新
    • this.setState((state, props) => newState, fn)
    • 这种方式的 state 反而更容易理解
    • fn 会在写入成功后执行
  • 写时会 shallow merge

    • setState 会自动更新 state 与旧 state 进行 第一层的合并

能用函数组件还是使用函数组件吧,因为函数组件更好用!

完。