【青訓營】- React Hook出新手村之路 - P2√

HappyYYT 2021-09-18 13:39:10 阅读数:575

react hook 出新 新手村 新手

useState:狀態管理; 使用頻率:*****

const [state, setState] = useState(initialState)

initialState是初始值,返回結果是數組類型[state, setState],第一個元素就是state狀態,第二個元素setState其實是一個方法,這個方法對state進行修改。

完整示例代碼可以在Demo中查看

image.png

在父組件調用<OfficialExample initialCount={0} />的關鍵代碼如下

function OfficialExample({ initialCount }) {
// 注意:如果直接設置useState(0)的話,在setCount裏需要對count進行類型轉換,即String轉成Number
const [count, setCount] = useState(initialCount);
return (
<> <h2>Count: {count}</h2> <button onClick={() => setCount(initialCount)}>Reset</button> <button onClick={() => setCount((prevCount) => prevCount - 1)>-</button> <button onClick={() => setCount((prevCount) => prevCount + 1)>+</button> </>
);
}
複制代碼

useEffect:副作用; 使用頻率:*****

useEffect(() => {effectFn(); return clearFn}, [...dependencies])

第一個參數effectFn()是一個帶有副作用邏輯的函數。它的裏面可以有一個返回值clearFn,這個返回值在useEffect每次被執行的時候,都會執行上一次useEffect的返回函數clearFn,因此我們可以在clearFn裏寫一些清楚副作用的邏輯;

如果你沒有return的話,盡管你在本頁面點擊鏈接跳到了另一個頁面,effectFn這個函數仍會在後臺執行,十分占用資源。

第二個參數[...dependencies]是一個數組類型的參數,可選。就是說如果我們不傳第二個參數的話,useEffect每次執行的時候第一個參數effectFn都會被執行。

如果我們傳入了第二個參數,但是第二個參數傳入的是一個空數組,那麼useEffect裏的副作用函數只會被執行一次,也就是組件被掛載完成後它只會被執行一次,後面都不會去執行。

// timer只會被執行1次,啟動setInterval只需要執行1次
// 如果沒有return的話,跳轉到其它頁面時,setInterval仍在執行
useEffect(()=>{
const timer = setInterval(() => {
// 邏輯
}, 1000);
return () => {
clearInterval(timer);
};
}, [])
複制代碼

如果我們傳入了第二個參數,且第二個參數有值,那麼當值被改變一次,effectFn就會被執行一次。

// 只要x的值改變了,就會執行一次effectFn邏輯
useEffect(()=>{
// effectFn邏輯
}, [x])
複制代碼

完整代碼可以在Demo中查看

image.png

useContext:上下文;使用頻率:*****

const value = useContext(MyContext)

接受一個參數MyContext,是createContext(initVal)的返回值(initVal可以不填),在上層組件給MyContext.Provider配置value屬性後,該組件就可以通過useContext獲取對應的value。

const themes = {
light: {foreground: "#000000",background: "#eeeeee"},
dark: {foreground: "#ffffff",background: "#222222"},
}
const ThemeContext = createContext(themes.light);
function OfficialExample() {
<ThemeContext.Provider value={themes.dark}>
<ThemedButton />
</ThemeContext.Provider>
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground}}> I am styled by theme context! </button>
)
}
複制代碼

完整代碼可以在Demo中查看

image.png

useReducer:useState的代替方案;使用頻率:*****

const [state, dispatch] = useReducer(reducer, initialCount, initFn)

相當於const [state, dispatch] = useReducer(reducer, initFn(initialCount))

如果你不了解reducer,還可以在學習Redux的時候複習鞏固它。題外話:Redux例子

reducer的責任大概是下圖這種感覺: Redux.jpg

完整代碼可以在Demo中查看

image.png

useCallback:回調;使用頻率:*****

useCallback(fn, [...dependencies])

它返回的是fn

關鍵代碼

const [x, setX] = useState(1);
// 如果把依賴項x清空什麼也不填只留一個[],那麼y的值將永遠是x的初始值(1)的計算結果。
const getY = useCallback(() => {
return 2 * x + 1;
}, [x])
複制代碼

完整代碼可以在Demo中查看

image.png

useMemo:相當於useCallback;使用頻率:*****

useMemo(fn, [...dependencies])

它返回的是fn(),即函數執行的返回值。所以useMemo(() => fn, [deps])相當於useCallback(fn, [deps]),傳入useMemo的() => fn這個函數的返回值是fn;而useCallback是傳入什麼就返回什麼,它的返回值就是傳入的fn,所以兩者相當。

完整代碼可以在Demo中查看

image.png

useRef:整個生命周期裏保存可變值;使用頻率:*****

const refContainer = useRef(initialValue)

它可以很方便地保存任何可變值且在組件的整個生命周期內持續存在。

關鍵代碼:

 function TextInputWithFocusBtn() {
const inputEl = useRef(null);
const onBtnClick = () => {
// current指向已掛載到DOM上的文本輸入元素
inputEl.current.focus();
};
return (
<> <input ref={inputEl} type="text" /> <button onClick={onBtnClick}>Focus the input</button> </>
)
}
複制代碼

完整代碼可以在Demo中查看

image.png

useImperativeHandle:使用ref時自定義暴露給父組件指定的屬性;使用頻率:*****

useImperativeHandle(ref, createHandle, [...dependencies])

它的使用伴隨著useRef和forwardRef。

關鍵代碼:

 function FancyInput(props, ref) {
const x = props.deps;
const inputRef = useRef();
useImperativeHandle(
ref,
() => ({
show: () => {
inputRef.current.value = x + 1;
}
}),
[x]
);
return <input ref={inputRef} placeholder={x} />;
}
function App() {
const [x, setX] = useState(1);
const ref = useRef(null);
function callChild() {
setX(x + 1);
ref.current.show();
}
return (
<> <FancyInput ref={ref} deps={x} /> <button onClick={callChild}>x+1</button> </>
)
}
複制代碼

完整代碼可以在Demo中查看

image.png

useLayoutEffect:和useEffect幾乎相同,只有調用時機不同;使用頻率:*****

useLayoutEffect(() => {effectFn(); return clearFn}, [...dependencies])

useLayoutEffect是在Dom渲染前調用effectFn;而useEffect是在Dom渲染後調用effectFn,這就是調用時機不同。

完整代碼可以在Demo中查看

image.png

image.png

版权声明:本文为[HappyYYT]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210918133910102C.html