使用hook的原因:
使用class创建组件,大型组件状态和逻辑组合在一起来,很难拆分和维护,使用不方便,所以改用hook。
hook作用:
在不使用class的情况下,也可以使用状态,也可以使用生命周期。使用函数创建数组。react hook就是加强版的函数式组件,完全可以不使用class,创建出一个复杂的组件。
hook钩子
react hook中提供很多的钩子,它的钩命名,都是use打头。
只在最顶层使用 Hook
只在 React 函数中调用 Hook
import React,{useState,useEffect} from "react"
export default ()=>{
let [count,setCount] = useState(0);
// 表示在函数内部顶层使用hook
useEffect(()=>{
if(count<=10){
document.title=`点击了${count}次`;
}
})
// 下面就不是在函数内部顶层使用hook,用法错误
/*if(count<=10){
useEffect(()=>{
document.title=`点击了${count}次`;
})
}*/
return(
<div>
<p>点击了{count}次</p>
<button onClick={ e=>setCount(count+1) }>加1</button>
</div>
)
}
import React,{ useState } from "react"
export default ()=>{
// 使用钩子,数组前面的是状态,后面都是修改状态的函数。
let [age,setAge] = useState(0);
let [name,setName] = useState("wangcai")
return(
<div>
<h2>我叫:{name},今年:{age}岁了</h2>
<button onClick={()=>{setAge(age+100 ); setName("xiaoqiang")}}>小小按钮</button>
</div>
)
}
useEffect 相当于类中的三个钩子函数:
useEffect的参数
// 下面的代码就类似于componentDidMount componentDidUpdate
useEffect(()=>{
document.title = `点击了${count}次`
})
// 下面的代码就类似于componentDidMount
useEffect(()=>{
document.title = `点击了${count}次`
},[])
// 当count发生了改变,那么就会执行componentDidUpdate,这样写DidMount也执行了
useEffect(()=>{
console.log("哈哈~")
document.title = `点击了${count}次`
},[count])
componentWillUnmount
import React,{useState,useEffect} from "react"
import ReactDOM from "react-dom"
export default ()=>{
let [count,setCount] = useState(0)
// 当一个组件将要卸载,它会调用一个钩子,叫componentWillUnmount
useEffect(()=>{
document.title = `点击了${count}次`
// return一个函数 return这个函数,就类似于componentWillUnmount
return ()=>{
// 此函数就类似于componentWillUnmount 一般在这里面做一个清理工作
console.log("组件将要卸载,你看一下,你的定时器清除了吗?")
}
},[]); // 加上[]相当于不会执行xxxDidUpdate
return(
<div>
<h2>点击了{count}次</h2>
<button onClick={()=>setCount(count+1)}>加1</button>
<button onClick={()=>ReactDOM.unmountComponentAtNode(document.getElementById("root"))}>杀死计算器</button>
</div>
)
}
useCallback callback是回调的意思
语法:useCallback(()=>{ dosomting() },[])
useCallback可以指定第2个参数
第一个参数第1次会执行,之后它会根据第2个参数的变化决定是否要执行
useCallback(()=>{
// 更新状态机
setWeight(weight+1)
},[age])
第1次回调函数执行,后面这个回调函数执行与否,取决于age这个状态是否变化,如果age状态变化,就执行,如果不变化就不执行
function Demo() {
let [age,setAge] = useState(1)
let [weight,setWeight] = useState(50)
function clickHeadle() {
setAge(age+1)
}
return(
<div>
<p>年龄:{age}岁</p>
<button onClick={clickHeadle}>年龄加1</button>
<p>体重:{weight}岁</p>
{/*<button onClick={()=>setWeight(weight+1)}>体重加1</button>*/}
<button onClick={
useCallback(()=>{
// 更新状态机
setWeight(weight+1)
},[age])
}>体重加1</button>
</div>
)
}
useReducers()钩子用来引入 Reducer 功能。
import React,{ useReducer } from "react";
// useReducer
let initState = {
count:0
}
function reducer(state,action) {
switch (action.type) {
case "increment":
/*let newState = JSON.parse(JSON.stringify(state))
newState.count = newState.count + 1;
return newState;*/
return {count:state.count+1}
case "decrement":
return {count:state.count-1}
default:
return state;
}
}
function Demo13() {
let [state,dispatch] = useReducer(reducer,initState)
return(
<div>
计数器:{state.count}
<div>
<button onClick={()=>dispatch({ type:"increment" })}>+</button>
<button onClick={()=>dispatch({ type:"decrement" })}>-</button>
</div>
</div>
)
}
export default Demo13;
如果需要在组件之间共享状态,可以使用useContext()。