React Hooks 是 React v16.8 版本引入了全新的 API。
React Hooks 基本概念
React 默認(rèn)提供的四個最常用的鉤子
- useState()
- useEffect()
- useContext()
- useReducer()
useState()
useState()用于為函數(shù)組件引入狀態(tài)(state)。純函數(shù)不能有狀態(tài),所以把狀態(tài)放在鉤子里面。
先看這個例子,這個例子用來顯示一個計數(shù)器。當(dāng)你點(diǎn)擊按鈕,計數(shù)器的值就會增加。
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
實例查看 點(diǎn)擊查看
useEffect()
useEffect()用來引入具有副作用的操作,最常見的就是向服務(wù)器請求數(shù)據(jù)。
import React, { useState, useEffect } from "react";
import "./styles.css";
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
export default App;
實例查看 點(diǎn)擊查看
上面例子可以看出 useEffect 相當(dāng)于生命周期 componentDidMount 、componentDidUpdate , useEffect 返回一個函數(shù),清除副作用,相當(dāng)于componentWillUnmount。
在某些情況下,每次渲染后都執(zhí)行清理或者執(zhí)行 effect 可能會導(dǎo)致性能問題。在 class 組件中,我們可以通過在 componentDidUpdate 中添加對 prevProps 或 prevState 的比較邏輯解決
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
document.title = `You clicked ${this.state.count} times`;
}
}
函數(shù)組件中,只要傳遞數(shù)組作為 useEffect 的第二個可選參數(shù)即可:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 僅在 count 更改時更新
如果想執(zhí)行只運(yùn)行一次的 effect(僅在組件掛載和卸載時執(zhí)行),可以傳遞一個空數(shù)組([])作為第二個參數(shù)。
useContext()
如果需要在組件之間共享狀態(tài),可以使用useContext()。
現(xiàn)在有兩個組件 Navbar 和 Messages,我們希望它們之間共享狀態(tài)。
第一步就是使用 React Context API,在組件外部建立一個 Context。
const AppContext = React.createContext();
組件封裝代碼如下
<AppContext.Provider value={{
username: 'react useContent'
}}>
<div className="App">
<Navbar/>
<Message/>
</div>
</AppContext.Provider>
AppContext.Provider提供了一個 Context 對象,這個對象可以被子組件共享。
Navbar 組件的代碼如下
const Navbar = () => {
const { username } = useContext(AppContext);
return (
<div className="navbar">
<p>{username}</p>
</div>
);
}
Message 組件的代碼如下
const Message = () => {
const { username } = useContext(AppContext);
return (
<div className="message">
<p>{username}</p>
</div>
);
}
實例查看 點(diǎn)擊查看
useReducer()
useReducers()鉤子用來引入 Reducer 功能。
const [state, dispatch] = useReducer(reducer, initialState);
useReducer 接受 Reducer 函數(shù)和狀態(tài)的初始值作為參數(shù),返回一個數(shù)組。數(shù)組的第一個成員是狀態(tài)的當(dāng)前值,第二個成員是發(fā)送 action 的dispatch函數(shù)。
下面是一個計數(shù)器的例子。用于計算狀態(tài)的 Reducer 函數(shù)如下。
const reducer = (state, action) => {
switch (action.type) {
case actions.INCREMENT:
return {
...state,
count: state.count + 1
};
case actions.DECREMENT:
return {
...state,
count: state.count - 1
};
default:
return state;
}
};
組件代碼如下
const [state, dispatch] = useReducer(reducer, { count: 1 });
return (
<div className="App">
<p>{state.count}</p>
<button onClick={() => dispatch({ type: actions.INCREMENT })}>+1</button>
<button onClick={() => dispatch({ type: actions.DECREMENT })}>-1</button>
</div>
);
實例查看 點(diǎn)擊查看