什麽是React Hooks?
React Hooks 提供了一种简洁的、函数式(FP)的程序风格,通过纯函数组件和可控的数据流来实现状态到 UI 的交互
首先先來看一段代碼
import React,{useState} from 'react'
function App(){
//聲明一個狀態變量
const [obj,setObjct]=useState({
count:0,
name:"alllife"
})
return (
<div className="App">
Count:{obj.count}
<button onClick={()=>setObjct({...obj,count:obj.count+1})}>+</button>
<button onClick={()=>setObjct({...obj,count:obj.count-1})}>-</button>
</div>
)
}
export default App
这个函数有自己的状态(count),同时它还可以更新自己的状态(setCount)。这个函数之所以这么了不得,就是因为它注入了一个hook–useState,就是这个hook让我们的函数变成了一个有状态的函数。
1,hooks與高階組件相比,沒有多餘的層級嵌套
2,同時不用再使用Class,所有組件都是Function,
這樣就暫時可以把生命周期鈎子函數丟在一邊
3,也就不用擔心this的問題了
而以上useState就是react自帶的一個hook函數,它的作用就是用來聲明狀態變量
useState它返回了一个数组,这个数组的第[0]项是当前当前的状态值,第[1]项是可以改变状态值的方法函数。
這樣這個函數就有自己的狀態了,但這遠遠不夠,hooks還提供了其他鈎子函數,比如:
useEffect提供了类似于componentDidMount等生命周期钩子的功能
useContext提供了上下文(context)的功能
之前我們操作異步請求,還需要考慮在哪個鈎子函數裏面進行,并且鈎子函數是同步的,有一定的執行的順序
import React,{useState,useEffect} from 'react'
function App(){
const [count,setCount]=useState(0)
// 类似于componentDidMount 和 componentDidUpdate:
useEffect(()=>{
console.log(count)
})
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
)
}
export default App
我們在給useEffect hook傳了一個匿名函數,當我們組件要渲染時,
它會先記住我們的useEffect,等dom更新後,它再依次執行我們的這個函數
這裏需要注意
1,react首次渲染和之後每次渲染都會調用傳給useEffect的函數,類似之前componentDidMount 和 componentDidUpdate:
2,useEffect的函數執行不會阻礙瀏覽器的更新視圖,也就是這些函數是異步執行的
let timer=null
function App(){
const [count,setCount]=useState(0)
useEffect(() => {
console.log("componetDidmount",count)
}, [count])
useEffect(() => {
timer=setInterval(()=>{
setCount(prevCount => prevCount + 1)
},1000)
return () => {
console.log("componentWillUnmount")
clearInterval(timer)
}
}, [])
return (
<div>
Count:{count}
<button onClick={()=>clearInterval(timer)}>clear</button>
</div>
)
}
export default App
第一个 useEffect 中,理解起来就是一旦 count 值发生改变,则打印值
而第二个 useEffect 当我们第二个参数传一个空数组[]时,其实就相当于只在首次渲染的时候执行。也就是componentDidMount加componentWillUnmount的模式。
useContext組件閒的傳值
對比一下兩種方式
const {Provider,Consumer} =React.createContext(null)
function Bar(){
return <Consumer>{color=><div>{color}</div>}</Consumer>
}
function Foo() {
return <Bar />;
}
function App() {
return (
<Provider value={"grey"}>
<Foo />
</Provider>
);
}
export default App
使用 useContext 可以解决 Consumer 多状态嵌套的问题
const colorContext =React.createContext()
function Bar(){
const color=useContext(colorContext)
return <div>{color}</div>
}
function Foo() {
return <Bar />;
}
function App(){
return (
<colorContext.Provider value={'red'}>
<Foo></Foo>
</colorContext.Provider>
)
}
export default App
useReducer和redux類似,唯一區別就是沒有redux提供的中間件
import React,{useReducer} from 'react'
const initialState={
count:0
}
function reducer(state,action){
switch (action.type){
case "increment":
return {count:state.count+action.payload}
case "decrement":
return {count:state.count-action.payload}
default:
return state.count;
}
}
function App(){
const [state,dispatch]=useReducer(reducer,initialState);
return (
<>
Count:{state.count}
<button onClick={()=>dispatch({type:'increment',payload:1})}>+</button>
<button onClick={()=>dispatch({type:'decrement',payload:1})}>-</button>
</>
)
}
export default App
缺点:
对一些钩子函数不支持。当下 v16.8 的版本中,还无法实现 getSnapshotBeforeUpdate 和 componentDidCatch 这两个在类组件中的生命周期函数。