hook 做为 react 新增特性,可以让我们在不编写 class 的情况下使用 state 以及其他的 react 特性。这里我们主要介绍几个特性useState、useEffect和useRef。
1、useState
useState主要用来改变一个state状态值。
我们先看一下基本写法:
let [state,setState] = useState({
n: 0
})
第一个参数state为useState的对象,也就是值。
第二个参数为改变第一个参数state值的方法。
案例:
import React,{useState} from 'react'
//useState需要单独导入,在这里将useState解构出来
export default function Zan(props) {
//1.解构useState
//2.第一个元素为useState的对象,也就是值
//3.第二的元素给改变值的方法
let [n,setN] = useState(0)
let change = ()=>{
setN(n+1)
}
return (
<div>
<button onClick={change}>赞 { state.n } </button>
</div>
)
}
总结:
(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
(2). 语法: const [xxx, setXxx] = React.useState(initValue)
(3). useState()说明:
参数: 第一次初始化指定的值在内部作缓存
返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
(4). setXxx()2种写法:
setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
2、useEffect
在react开发中,我们常在生命周期函数中进行一些操作。但是在函数组件中是没有生命周期函数的,因此官方提供了useEffect()副作用钩子。
React中的副作用操作:
发ajax请求数据获取
设置订阅 / 启动定时器
手动更改真实DOM
useEffect()相当于类组件中的:
componentDidMount()
componentDidUpdate()
componentWillUnmount() 。
基本写法:
useEffect(() => {
// 在此可以执行任何带副作用操作
return () => { // 在组件卸载前执行
// 在此做一些收尾工作, 比如清除定时器/取消订阅等
}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
第一个参数为回调函数。
第二个参数为数组,数组内存放要监听的元素。
注意:想要书写类似componentWillUnmount() 的函数,应写在第一个参数的return返回值里。
总结:
(1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
(2). React中的副作用操作:
发ajax请求数据获取
设置订阅 / 启动定时器
手动更改真实DOM
(3). 语法和说明:
useEffect(() => {
// 在此可以执行任何带副作用操作
return () => { // 在组件卸载前执行
// 在此做一些收尾工作, 比如清除定时器/取消订阅等
}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
(4). 可以把 useEffect Hook 看做如下三个函数的组合
componentDidMount()
componentDidUpdate()
componentWillUnmount()
案例:
父组件
import React,{useState, useEffect} from 'react'
import Son from './Son'
export default function App() {
let [n,setN] = useState(0)
let [m,setM] = useState(0)
let [show,setShow] = useState(true)
let add = ()=>{
setN(n + 1)
}
//DidMount,DidUpdate
//第一个参数为回调函数
//第二个参数为数组,数组内存放要监听的元素
useEffect(()=>{
let div = document.getElementById('app')
// console.log(div);
console.log('useEffect...', div);
return ()=>{
console.log('useEffect...return....');
}
}, [n,m])
return (
<div id="app">
{ n }
<button onClick={add}>+</button>
<hr></hr>
{m}
<button onClick={()=>{setM(m+1)}}>+</button>
<hr></hr>
<button onClick={()=>{ setShow(!show) }}>切换</button>
{ show && <Son></Son> }
</div>
)
}
子组件:
import React,{useEffect} from 'react'
export default function Son() {
let add = ()=> {
}
useEffect(()=>{
console.log('useEffect...Son...');
return ()=>{
console.log('useEffect....return....Son....');
}
}, [])
return (
<div>
<h3>Son.jsx</h3>
</div>
)
}
3、useRef
(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样
案例:
import React from 'react'
import ReactDOM from 'react-dom'
function Demo(){
const myRef = React.useRef()
//提示输入的回调
function show(){
alert(myRef.current.value)
}
return (
<div>
<input type="text" ref={myRef}/>
<button onClick={show}>点我提示数据</button>
</div>
)
}
export default Demo
demo:
import React from 'react'
import ReactDOM from 'react-dom'
function Demo(){
//console.log('Demo');
const [count,setCount] = React.useState(0)
const myRef = React.useRef()
React.useEffect(()=>{
let timer = setInterval(()=>{
setCount(count => count+1 )
},1000)
return ()=>{
clearInterval(timer)
}
},[])
//加的回调
function add(){
//setCount(count+1) //第一种写法
setCount(count => count+1 )
}
//提示输入的回调
function show(){
alert(myRef.current.value)
}
//卸载组件的回调
function unmount(){
ReactDOM.unmountComponentAtNode(document.getElementById('root'))
}
return (
<div>
<input type="text" ref={myRef}/>
<h2>当前求和为:{count}</h2>
<button onClick={add}>点我+1</button>
<button onClick={unmount}>卸载组件</button>
<button onClick={show}>点我提示数据</button>
</div>
)
}
export default Demo