1. react使用hook的意義
- class組件可以定義自己的state,用來保存組件自己內(nèi)部的狀態(tài),函數(shù)式組件不可以,因為函數(shù)每次調(diào)用都會產(chǎn)生新的臨時變量;
-
class組件有 自己的生命周期 ,我們可以在 對應的生命周期中完成自己的邏輯, 比如在componentDidMount中發(fā)送網(wǎng)絡請求,并且該生命周期函數(shù)只會執(zhí)行一次,如果在函數(shù)中發(fā)送網(wǎng)絡請求,意味著每次重新渲染都會重新發(fā)送一次網(wǎng)絡請求;
-
class組件可以 在狀態(tài)改變時只會重新執(zhí)行render函數(shù) 以及 我們希望重新調(diào)用的生命周期函數(shù)componentDidUpdate 等,函數(shù)式組件在重新渲染時,整個函數(shù)都會被執(zhí)行,似乎沒有什么地方可以只讓它們調(diào)用一次;
hook的出現(xiàn)就是為了解決函數(shù)式組件中實現(xiàn)class組件的很多特性,它可以讓我們在不編寫class的情況下使用state以及其他的React特性;
2. useState Hook解析
- 參數(shù):初始化值,如果不設置為undefined;
-
返回值:數(shù)組,包含兩個元素,元素一: 當前狀態(tài)的值(第一調(diào)用為初始化值) ,元素二: 設置狀態(tài)值的函數(shù) ;
注意:
- 只能在函數(shù)最外層調(diào)用 Hook。不要在循環(huán)、條件判斷或者子函數(shù)中調(diào)用;
- 只能在 React 的函數(shù)組件中調(diào)用 Hook。不要在其他 JavaScript 函數(shù)中調(diào)用;
import { memo, useState } from "react";
// 普通的函數(shù), 里面不能使用hooks
// 在自定義的hooks中, 可以使用react提供的其他hooks: 必須使用use開頭
// function useFoo() {
// const [ message ] = useState("Hello World")
// return message
// }
function CounterHook(props) {
const [counter, setCounter] = useState(0)
const [name] = useState("why")
console.log(name)
// const message = useFoo()
return (
<div>
<h2>當前計數(shù): {counter}</h2>
<button onClick={e => setCounter(counter+1)}>+1</button>
<button onClick={e => setCounter(counter-1)}>-1</button>
</div>
)
}
3. useEffect Hook解析
- Effect Hook 可以讓你來完成一些類似于class中生命周期的功能;
-
類似于 網(wǎng)絡請求、手動更新DOM、一些事件的監(jiān)聽 ,都是 React更新DOM的一些副作用;
-
對于完成這些功能的Hook被稱之為 Effect Hook;
useEffect的解析:
- 通過useEffect的Hook,可以告訴React需要在渲染后執(zhí)行某些操作;
-
useEffect 要求我們傳入一個回調(diào)函數(shù) ,在React 執(zhí)行完更新DOM操作之后 ,就 會回調(diào)這個函數(shù);
-
默認情況下, 無論是第一次渲染之后 ,還是每次更新之后,都會 執(zhí)行這個 回調(diào)函數(shù);
清除Effect:
- 比如我們之前的事件總線或Redux中手動調(diào)用subscribe;
-
都需要在 componentWillUnmount有對應的取消訂閱;
// 負責告知react, 在執(zhí)行完當前組件渲染之后要執(zhí)行的副作用代碼
useEffect(() => {
// 1.監(jiān)聽事件
// const unubscribe = store.subscribe(() => {
// })
// function foo() {
// }
// 返回值: 回調(diào)函數(shù) => 組件被重新渲染或者組件卸載的時候執(zhí)行
return () => {
}
})
-
某些代碼我們只是 希望執(zhí)行一次即可 ,類似于componentDidMount和componentWillUnmount中完成的事情;(比如網(wǎng)絡請求、訂閱和取消訂閱);
-
多次執(zhí)行也會導致一定的性能問題;
useEffect的解決方式:
useEffect(() => {
console.log("修改title:", count)
}, [count])
useEffect(() => {
console.log("監(jiān)聽redux中的數(shù)據(jù)")
return () => {}
}, [])
useEffect(() => {
console.log("監(jiān)聽eventBus的why事件")
return () => {}
}, [])
useEffect(() => {
console.log("發(fā)送網(wǎng)絡請求, 從服務器獲取數(shù)據(jù)")
return () => {
console.log("會在組件被卸載時, 才會執(zhí)行一次")
}
}, [])
?4. useContext Hook解析
在開發(fā)中,要在組件中使用共享的Context有兩種方式:
- 類組件可以通過 類名.contextType = MyContext方式,在類中獲取context;
-
多個Context或者在函數(shù)式組件中通過 MyContext.Consumer 方式共享context;
- Context Hook允許我們通過Hook來直接獲取某個Context的值;
contxt.js文章來源:http://www.zghlxwxcb.cn/news/detail-716591.html
import { createContext } from "react";
const UserContext = createContext()
const ThemeContext = createContext()
export {
UserContext,
ThemeContext
}
App.jsx文章來源地址http://www.zghlxwxcb.cn/news/detail-716591.html
import React, { memo, useContext } from 'react'
import { UserContext, ThemeContext } from "./context"
const App = memo(() => {
// 使用Context
const user = useContext(UserContext)
const theme = useContext(ThemeContext)
return (
<div>
<h2>User: {user.name}-{user.level}</h2>
<h2 style={{color: theme.color, fontSize: theme.size}}>Theme</h2>
</div>
)
})
export default App
5. useReducer Hook解析
- 在某些場景下,如果state的處理邏輯比較復雜,我們可以通過useReducer來對其進行拆分;
-
或者這次修改的state需要依賴之前的state時,也可以使用;
import React, { memo, useReducer } from 'react'
function reducer(state, action) {
switch(action.type) {
case "increment":
return { ...state, counter: state.counter + 1 }
case "decrement":
return { ...state, counter: state.counter - 1 }
case "add_number":
return { ...state, counter: state.counter + action.num }
case "sub_number":
return { ...state, counter: state.counter - action.num }
default:
return state
}
}
const App = memo(() => {
const [state, dispatch] = useReducer(reducer, { counter: 0, friends: [], user: {} })
return (
<div>
<h2>當前計數(shù): {state.counter}</h2>
<button onClick={e => dispatch({type: "increment"})}>+1</button>
<button onClick={e => dispatch({type: "decrement"})}>-1</button>
<button onClick={e => dispatch({type: "add_number", num: 5})}>+5</button>
<button onClick={e => dispatch({type: "sub_number", num: 5})}>-5</button>
<button onClick={e => dispatch({type: "add_number", num: 100})}>+100</button>
</div>
)
})
export default App
6.?useRef Hook解析
- 用法一:引入DOM(或者組件,但是需要是class組件)元素;
-
用法二:保存一個數(shù)據(jù),這個對象在整個生命周期中可以保存不變;
import React, { memo, useRef } from 'react'
const App = memo(() => {
const titleRef = useRef()
const inputRef = useRef()
function showTitleDom() {
console.log(titleRef.current)
inputRef.current.focus()
}
return (
<div>
<h2 ref={titleRef}>Hello World</h2>
<input type="text" ref={inputRef} />
<button onClick={showTitleDom}>查看title的dom</button>
</div>
)
})
export default App
到了這里,關于React Hooks解析的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!