一、使用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>
建议还是使用第一种哈 看起来清晰