react-hook學習
hooks技術不是一門新的技術,而是一種設計思想。
自定義hooks更像是一種約定,而不是一種功能,一般以use
開頭的,並呼叫其他hook,就可以稱為自定義Hooks(自定義的Hook中,最裡面一定是使用了useEffect函式)。
注意:
每次呼叫 setSate的類似函式(例如:setCount),都會從新執行整個函式元件。
useState()
const [count, setCount] = useState(0);
/*
初始化一個狀態變數並帶有初始值(0)
count:初始化的狀態變數
setCount:改變這個狀態的函式(類似與setState())
*/
useContext()
在類元件中有constructor函式,可以用來接收pops屬性的值。
但是函式式元件中沒有constructor函式,也就沒有了接受props屬性的地方,那麼在這種情況下父元件想向子元件傳值就有問題了,為了解決這個問題,引入了useContext()
函式。
作用:
-
實現跨越元件層級傳遞變數,提供全域性共享。
useContext()
解決元件之間傳遞的問題。與useReducer()
配合使用,可以實現類似於redux
的功能。redux
整個應用中統一狀態管理。 -
context是對它所包含的元件樹提供全域性共享資料的一種技術。
cont [state, dispatch] = useContext(context) /* useContext(context) 接收一個context引數,這個context是由React.createContext(defaultValue)所建立的 */ const {Provider, Consumer} = context = React.createContext(defaultValue); function Parent(){ const [count, setCount] = useState(0); return( <> <div>{count}</div> <button onClick={()=>{setCount(count+1)}}>Click Me</button> <Provider value={count}> <Child /> </Provider> </> ) } function Child(){ const count = useContext(context); return (<h2>{count}</h2>) } /* 既然是解決父元件想子元件傳值的問題的,那麼父元件是如何向子組傳遞值的呢? 1. 父元件需要把將要傳遞的值放到context中 2. 子元件使用useContext()獲取父元件傳遞的值 //定義一個父元件最外層的context變數(可以單獨成檔案,然後再父元件和子元件中分別引入使用) const {Provider, Consumer} = context = React.createContext(defaultValue); Provider是傳值方(context.Providert) Consumer是接收方(context.Consumer) function Parent(){ const [count, setCount] = useState(0); return( <> <div>{count}</div> <button onClick={()=>{setCount(count+1)}}>Click Me</button> //將父元件要傳遞的值放入到context中 <Provider value={count}> //這樣父元件中的count發生變化後,子元件的值就會發生改變 <Child /> </Provider> </> ) } //重點 重點 重點 function Child(){ //使用useContext()接收父元件傳遞過來的屬性值,這裡useContext會獲取到離子元件最近的父元件傳遞過來的值 //同時需要注意的是,這裡的context必須要與父元件是相同的context,才可以實現資料的共享。 const count = useContext(context); return (<h2>{count}</h2>) } */
useEffect(func,[deps])
相當於類元件中的componentDidMount()
、componentDidUpdate()
以及componentWillUnmount()
的合併,即完成DOM修改後的呼叫函式
func:表示DOM渲染後需要執行的函式體。
deps:表示這個useEffect()
的依賴項,依賴項發生改變,就會再次執行func函式體。
useEffect()
如果函式中由需要清除的副作用,就需要在useEffect()
函式體內返回一個函式
useEffect(()=>{ //.... return ()=>{ //需要清除的副作用 } },[])
useReducer(reducer,initState)
useReducer(reducer,initState)
用來管理state狀態(多個狀態需要同時修改時,建議使用:例如:登入驗證)
import React,{useReducer} from 'react'
export default function ReducerDemo() {
const [count, dispath] = useReducer((state,action)=> {
switch(action){
case 'add':
return state + 1;
case 'sub':
return state - 1;
default:
return state;
}
}, 0);
return (
<div>
<h1 className="title">{count}</h1>
<button className="btn is-primary"
onClick={()=> dispath('add')}
>Increment</button>
<button className="btn is-warnning"
onClick={()=> dispath('sub')}
>Decrement</button>
</div>
)
}
/*
const [count, dispatch] = useReducer(reducer,initState)
reducer: 一個負責改變state的值的函式,
這個函式由兩個引數:reducer(state,action)
state:初始狀態
action:reducer函式會根據action的型別來判斷將怎麼改變這個state
count:狀態改變後的值
dispatch:一個觸發reducer的機制,在元件中呼叫。(重要)
return [
...state,
{
id:10,
name:"haha"
}
]
這句話的意思是,先copy一個state,然後修改這個state
*/
useRef(initValue)
const like = useRef(0);
//貫穿元件的整個生命週期,元件重新渲染後like的值不會改變,保持原值。
useLayoutEffect(func,[deps])
佈局副作用:
useEffect在瀏覽器渲染完成後執行
useLayoutEffect在瀏覽器渲染完成前執行
特點:
useLayoutEffect總是比useEffect先執行
useLayoutEffect裡面的任務最好影響layout(佈局)
注意:
最好是使用useEffect(為了使用者體驗最好)
useCallback(func,[deps])
解決:函式元件的每一次呼叫都會執行其內部的所有邏輯,那麼會帶來較大的效能損耗。
useMemo()
和useCallback()
就是解決這些問題的殺手鐗。
- useMemo() 返回快取的變數
- useCallback() 返回快取的函式
const funA = useCallback(funcB, [deps]);
//將傳遞進來的funcB返回給funcA,並且將這個結果進行快取,如果依賴改變了,就會返回新的函式。
注意:
useMemo()
,useCallback()
,useEffect()
都是自帶閉包的,即元件每次重新渲染,其都會捕獲當前元件函式上下文中的狀態(stat,props),所以它反映的也都是元件當前的狀態。
useMemo(initValue)
類似與useCallback,只是useMemo返回的是快取的變數。
const valueA = useMemo(2);
//valueA變數會一直保留,重新渲染元件時不會重新定義這個變數。