一、使用hooks

因为函数组件是无状态的 所以 react提供了Hooks 能够把 把函数组件变成有状态的组件(提供state)

在React v16.8之前:class组件(提供状态) + 函数组件(展示内容)
React v16.8及其以后:
1.class 组件(提供状态)+ 函数组件(展示内容)
2.Hooks(提供状态) + 函数组件(展示内容)
3.混用以上两种方式:部分功能用class组件,部分功能用Hooks

使用步骤

1.导入 useState 函数

2.调用 useState,传入初始值,返回状态和修改状态的函数

3.使用

(1)在jsx中展示状态

(2)特定的时机调用修改状态的函数来改状态

  普通写法

import React, { useState } from 'react'

const Ren = function () {
  const num = useState(0)
   const number = num[0]
   const add = num[1]
  return <div>
    <div>初始值 {number}</div>
    <div onClick={() => { add(number + 1) }}>点击 加1</div>
  </div>
}

 useState(0) 就是定义初始值变量

number 是 返回的装填 add 是 要修改状态的函数

结构写法

import React, { useState } from 'react'

const Ren = function () {
  const num = useState(0)
  // 第一个参数是 状态 第二个参数是要修改状态的函数
  const [number, add] = num
  return <div>
    <div>初始值 {number}</div>
    <div onClick={() => { add(number + 1) }}>点击 加1</div>
  </div>
}

二、表单元素

import React, { useState } from 'react'
import ReactDOM from 'react-dom/client'

const Ren = function () {
  const num = useState(0)
  // 结构写法
  const [number, setNum] = num
  function getNum () {
    console.log(number)
  }
  return <div>
    <input value={number} onChange={(e) => { setNum(e.target.value) }}></input>
    {/* <div onClick={() => { console.log(number) }}>点击获取</div> */}
    <div onClick={getNum}>点击获取</div>
  </div>
}


const root = ReactDOM.createRoot(document.getElementById('root'))

root.render(
  <React.StrictMode>
    <Ren />
  </React.StrictMode>
)

只需要给value 绑定初始值 onChange的 时候调用函数就可以啦

 三、useState和setState的两种写法

import React, { useState } from 'react'
import ReactDOM from 'react-dom/client'

const Ren = function () {
  // const num = useState(0)
  // 第二种写法
  const num = useState(() => 0)
  // 结构写法
  const [number, setNum] = num

  function addNum () {
    // console.log(number)
    setNum(number + 1) //覆盖num
    setNum(number + 1) // 覆盖num
    setNum(number + 1) // 覆盖num
  }

  return <div>
    <input value={number} onChange={(e) => { setNum(e.target.value) }}></input>
    <div onClick={addNum}>点击+1</div>
  </div>
}


const root = ReactDOM.createRoot(document.getElementById('root'))

root.render(
  <React.StrictMode>
    <Ren />
  </React.StrictMode>
)

useState 第一种写法

const num = useState(0)
useState 第二种写法
const num = useState(() => 0)

本质上是没有区别的 只不过第二种是一个函数  可以在里面做一些判断、打印

在上面setNum 中执行了三遍  但是每次点击输出的结果只是加1 类似于每次都是直接去修改 number 类似于 覆盖 第二次修改覆盖第一次

如果想执行多变 react提供了另一种写法

function addNum () {
    setNum((a) => { return a + 1 }) // 上一次执行完在执行下一次
    setNum((a) => { return a + 1 })
    setNum((a) => { return a + 1 })
  }

他会去等 第一行执行完毕了 再去执行第二行 

函数倒计时案例

import React, { useState } from 'react'
import ReactDOM from 'react-dom/client'

const Ren = function () {
  console.log('执行啦')
  // const [number, setNum] = useState(3)
  const [number, setNum] = useState(() => {
    console.log('useState只执行一遍')
    return 3
  })

  function addNum () {
    console.log('函数内部')
    const timer = setInterval(() => {
      setNum((a) => {
        if (a == 1) clearInterval(timer)
        return a - 1
      })

    }, 1000)
  }
  return <div>
    <div>{number}</div>
    <button onClick={addNum}>倒计时</button>
  </div>
}


const root = ReactDOM.createRoot(document.getElementById('root'))

root.render(
  <React.StrictMode>
    <Ren />
  </React.StrictMode>
)

useState只会执行一次 这个值保存在react里 如果执行多次的话 那么每次初始值都是3永远都改变不了 
而值发生改变了整个函数组件都会重新执行一遍

 四、定义useState的两种形式

第一种就是正常定义了

const [a, setA] = useState(0)

  const [b, setB] = useState(1)

第二种

const [obj, setObj] = useState({ c: 1, d: 1 })
const objEdit = () => {
    // 直接把当前值替换了
    // setObj({ c: 2 })
    // 如果想改变一个值
    setObj({ ...obj, c: 2 })
  }

 <button onClick={objEdit}>c,d+1</button>
  <div>{obj.c},{obj.d} </div>

建议还是使用第一种哈 看起来清晰