「React」props & state & setState

203 阅读1分钟

对于数据,我们只关心三点:如何初始化,如何读,如何写

props

外部数据

props 的作用

  • 接受外部数据

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

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

初始化

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

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

怎么读

通过 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 (
       <div>n: {this.props.name}</div> // 使用 this.props.name 来读
     )
   }
 }

怎么写

  • 永远不要去改 props!
  • 外部数据,就应该由外部更新

state & setState

内部数据

初始化

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

怎么读

通过 this.state.xxx 来读

怎么写

通过 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 进行 第一层的合并