React中的state,事件及SetSate

天藍藍tao發表於2018-12-24

state的建立方法

類元件才是有狀態的元件,如果是Arrow Function建立的元件,也叫做無狀態元件(stateless compoment)

1.react裡的第一種state定義

export default class App extends Component {
    state = {
        name: 'tianlanlan',
        age: 18,
        skills: [{
            id: 1,
            title: '吃飯'
          }, {
            id: 2,
            title: '睡覺'
          },{
            id: 3,
            title: '打豆豆'
          }]
    }
    
   render() {
    return (
      <Fragment>
        <dl>
          <dt>名字</dt>
          <dd>{this.state.name}</dd>
        </dl>
        <dl>
          <dt>年齡</dt>
          <dd>{this.state.age}</dd>
        </dl>
        <dl>
          <dt>技能</dt>
          {
            // 這裡是語句,迴圈輸出,在react裡就是直接用map。而不是for
            // 而且這裡不需要直接賦值,而是直接寫map語句
            // 在React的迴圈裡,必須要有一個key
            this.state.skills.map(item => {
              return (
                <dd key={item.id}>{item.title}</dd>
              )
            })
          }
        </dl>
      </Fragment>
    )
  }
}
複製程式碼

React中的state,事件及SetSate
2.react裡的第二種state定義(大多使用第二種)constructor只執行一次

constructor () {
    super();
    this.state = {
          name: 'tianlanlan',
          age: 18,
          skills: [{
            id: 1,
            title: '吃飯'
          }, {
            id: 2,
            title: '睡覺'
          },{
            id: 3,
            title: '打豆豆'
          }]
        }
    }
    render() {
    return (
      <Fragment>
        <dl>
          <dt>名字</dt>
          <dd>{this.state.name}</dd>
        </dl>
        <dl>
          <dt>年齡</dt>
          <dd>{this.state.age}</dd>
        </dl>
        <dl>
          <dt>技能</dt>
          {
            // 這裡是語句,迴圈輸出,在react裡就是直接用map。而不是for
            // 而且這裡不需要直接賦值,而是直接寫map語句
            // 在React的迴圈裡,必須要有一個key
            this.state.skills.map(item => {
              return (
                <dd key={item.id}>{item.title}</dd>
              )
            })
          }
        </dl>
      </Fragment>
    )
  }
複製程式碼

React中的state,事件及SetSate
注意:

state的主要目的是為了把一些需要改變的資料管理起來,方便後期用資料決定顯示的思想來進行重新渲染

事件繫結

1.箭頭函式

定義一個事件,把一個箭頭函式賦值給一個變數,在呼叫的時候,就用this.handleAgeAdd來進行呼叫

(1) 在react裡不能!不能!不能!直接修改state,這樣只是值更改了,不會觸發render()

  handleAgeAdd = ()=> {
    this.state.age++
    console.log(this.state.age)
  }
複製程式碼

React中的state,事件及SetSate

注意:

React不允許直接修改state,需要呼叫setState的方法來進行修改,每一次的state修改會直接反映到UI介面上

(2)如果需要更新state,必須!必須!必須!呼叫setState方法

handleAgeAdd = ()=> {
    this.setState({
      // 這裡不能用++
      age: this.state.age + 1
    })
    console.log(this.state.age)
  }
複製程式碼

React中的state,事件及SetSate

2.不是箭頭函式

(1)setState的第一個引數,可以是一個物件

handleAgeAdd () {
    this.setState({
      age: this.state.age + 1
    }, () => {
      // 如果要獲取到最新的state,需要在setState的第二個回撥函式裡去獲取
      console.log('回撥函式列印:', this.state.age)
    })
    // 這裡永遠列印出來的是上一次的state,而不是setState之後的,因為setState是非同步的
    console.log('外面列印:', this.state.age)
  }
複製程式碼

React中的state,事件及SetSate
注意:

如果要獲取到最新的state,需要在setState的第二個回撥函式裡去獲取

setState外面列印出來的是上一次的state,而不是setState之後的,因為setState是非同步的

(2)setState的第一個引數,也可以是一個方法,但是,這個方法裡必須要return一個物件

handleAgeAdd () {
    // 這個方法裡的第一個引數,特別有用,是上一次的state
    this.setState((prevState) => {
      console.log(prevState)
      return {
        age: prevState.age + 1
      }
    })
  }
複製程式碼

React中的state,事件及SetSate

注意:

// 如果是箭頭函式,直接呼叫方法
<button onClick={this.handleAgeAdd}>增加一歲</button>
複製程式碼
// 如果不是箭頭函式, 需要bind(this)
// 不推薦在render方法裡bind(this),因為render方法會隨著狀態的更改,多次執行
<button onClick={this.handleAgeAdd.bind(this)}>增加一歲</button>
複製程式碼
// 如果不是箭頭函式定義的方法,推薦在constructor這裡進行bind(因為constructor只執行一次)
this.handleAgeAdd = this.handleAgeAdd.bind(this)
複製程式碼

補充:

1. input 中的 onchange 事件中有一個event物件

handleInputChange = (e) => {
    console.log(e)
  }
複製程式碼
<input
  type="text"
  onChange={this.handleInputChange}
/>
複製程式碼

React中的state,事件及SetSate

handleInputChange = (e) => {
    console.log(e.target)
  }
複製程式碼

React中的state,事件及SetSate

2.push的返回值

todos: this.state.todos.push(todo)
複製程式碼

注意:

這裡的push要出錯,因為push是更改了原來state裡的值,但是返回的值又是一個長度,所以這樣得到的todos就是一個數字,而不是一個陣列

可以寫成:

this.setState({
1.todos: this.state.todos.concat(todo)
2.todos: [...this.state.todos, todo]
3.todos: this.state.todos.slice().concat(todo)
})

// 深拷貝: 為了不破壞原有的值,我們需要深拷貝,JSON的方式做深拷貝,如果拷貝的內容中含有方法,則不可以拷貝
4.const todos = cloneDeep(this.state.todos)
    todos.push(todo)
    this.setState({
      todos
    })
5.const todos = JSON.parse(JSON.stringify(this.state.todos))
    todos.push(todo)
        this.setState({
          todos
        })
複製程式碼

3.createRef

// 要想使用ref, 需要引入createRef方法
import React, { Component, createRef } from 'react'

export default class Input extends Component {
  constructor() {
    super()
    // 初始化一個ref
    this.input = createRef();
  }
  
  handleAddClick = () => {
    this.setState({
      inputValue: ''
    }, () => {
      // 獲取ref
      console.log(this.input.current)
      // 新增完成之後,自動獲取焦點
      this.input.current.focus()
    })
  }
  
  render() {
    return (
      <div>
        <input
          type="text"
          // 給input的ref賦值
          ref={this.input}
          value={this.state.inputValue}
          onChange={this.handleInputChange}
        />
        <button onClick={this.handleAddClick}>新增</button>
      </div>
    )
  }
複製程式碼

聚焦之前

React中的state,事件及SetSate

自動獲取焦點

React中的state,事件及SetSate

相關文章