React Hooks
是什麼
Hook是React16.8的新增特性,可以在不使用類元件的情況下使用state
及React的其它特性。
七大Hook
useState
狀態useEffect
鉤子,還有它的兄弟useLayoutEffect
useContext
上下文useReducer
代替 ReduxuseMemo
快取,還有它的小弟useCallback
useRef
引用- 自定義
Hook
混合
useState
基本語法
const [X, setX] = React.useState(X的初始值)
簡單示例
function App() {
const [user,setUser] = useState({name:'Varian', age: 18})
const onClick = ()=>{
setUser({
name: 'Janye'
})
}
return (
<div className="App">
<h1>{user.name}</h1>
<h2>{user.age}</h2>
<button onClick={onClick}>Click</button>
</div>
);
}
我們會發現,點選按鈕之後,age
消失了,而我們明明只改了 name
呀,為什麼呢?
簡單來說就是前後是兩個完全不相關的物件。
展開講的話 React
在資料變化時會建立新的虛擬 DOM
物件,然後將這個虛擬 DOM
物件跟原虛擬 DOM 進行一個 DOM Diff
,得到一個最小的變化過程 Patch
,並把這個 Patch
渲染到頁面上,Diff
的時候發現新物件沒有 age
這個屬性,於是就把它刪除了。
於是在使用 useState
的時候我們需要注意兩個地方:
- 想要原來的值,必須在 setX 裡先進行復制,類似這樣
setUser({...user, name: 'Janye'})
setX(obj)
時,obj
的地址必須改變
useEffect
useEffect
的作用主要是用來解決函式元件如何像類元件一樣使用生命週期鉤子的問題。
它有三個使用場景:
- 作為
componentDidMount
使用,第二個引數為空陣列[]
- 作為
componentDidUpdate
使用,第二個引數為指定依賴 - 作為
componentWillUnmount
使用,通過return
簡單示例
const BlinkyRender = () => {
const [value, setValue] = useState(0);
useEffect(() => {
document.querySelector('#x').innerText = `value: 1000`
}, [value]);
return (
<div id="x" onClick={() => setValue(0)}>value: {value}</div>
);
};
ReactDOM.render(
<BlinkyRender />,
document.querySelector("#root")
);
它跟 useLayoutEffect
有什麼區別?
useEffect
在瀏覽器渲染完成後執行,useLayoutEffect
在瀏覽器渲染前執行,useLayoutEffect
總是比 useEffect
先執行。
為了使用者體驗(先渲染就能先看到),通常我們應該先用useEffect
。
useContext
如果我們想在元件之間共享狀態的話,可以使用 useContext
。
它的使用可以分為三個步驟:
- 使用
C = createContext(initial)
建立上下文 - 使用
<C.provider>
圈定作用域 - 在作用域內使用
useContext(C)
來使用上下文
簡單示例
const C = createContext(null);
function App() {
console.log("App 執行了");
const [n, setN] = useState(0);
return (
<C.Provider value={{ n, setN }}>
<div className="App">
<Baba />
</div>
</C.Provider>
);
}
function Baba() {
const { n, setN } = useContext(C);
return (
<div>
我是爸爸 n: {n} <Child />
</div>
);
}
function Child() {
const { n, setN } = useContext(C);
const onClick = () => {
setN(i => i + 1);
};
return (
<div>
我是兒子 我得到的 n: {n}
<button onClick={onClick}>+1</button>
</div>
);
}
useReducer
如果要一句話解釋 useReducer
的話,它是用來代替 Redux 的,或者說,是一個加強版的 useState
。
使用上來說,一共有四步:
- 建立初始值
initialState
- 建立所有操作
reducer(state, action)
- 傳給
useReducer
,得到讀和寫API
- 呼叫 寫
({type: '操作型別'})
簡單示例
const initial = {
n: 0
};
const reducer = (state, action) => {
if (action.type === "add") {
return { n: state.n + action.number };
} else if (action.type === "multi") {
return { n: state.n * 2 };
} else {
throw new Error("unknown type");
}
};
function App() {
const [state, dispatch] = useReducer(reducer, initial);
const { n } = state;
const onClick = () => {
dispatch({ type: "add", number: 1 });
};
const onClick2 = () => {
dispatch({ type: "add", number: 2 });
};
return (
<div className="App">
<h1>n: {n}</h1>
<button onClick={onClick}>+1</button>
<button onClick={onClick2}>+2</button>
</div>
);
}
useMemo
基本語法:
useMemo(回撥函式, [依賴])
類似與 Vue 的計算屬性 computed
,useMemo
具有快取,依賴改變才重新渲染的功能。
跟它的小弟 useCallback
的唯一區別是:useMemo
可以快取所有物件,useCallback
只能快取函式。
useCallback(x => log(x), [m])
等價於 useMemo(() => x => log(x), [m])
useRef
主要作用是建立一個資料的引用,並讓這個資料在 render
過程中始終保持不變。
基本語法:
const count = useRef(0),讀取用 count.current
封裝 Echarts 時的例子
export function ReactEcharts(props) {
const {option, loading} = props
const container = useRef(null)
const chart = useRef(null)
useEffect(() => {
const width = document.documentElement.clientWidth
const c = container.current
console.log(c)
c.style.width = `${width - 20}px`
c.style.height = `${(width - 20) * 1.2}px`
chart.current = echarts.init(c, 'dark')
}, []) // [] - mounted on first time
useEffect(() => {
chart.current.setOption(option)
}, [option]) // when option change 類似 vue 的 watch
useEffect(() => {
if (loading) chart.current.showLoading()
else chart.current.hideLoading()
}, [loading])
return (
<div ref={container}/>
)
}
自定義Hook
可以理解為我們可以把上面的 Hook
按照實際的需求混合起來,封裝成一個函式,給一個簡單示例:
const useList = () => {
const [list, setList] = useState(null);
useEffect(() => {
ajax("/list").then(list => {
setList(list);
});
}, []); // [] 確保只在第一次執行
return {
list: list,
setList: setList
};
};
export default useList;
相關文章
- [react] hooksReactHook
- react之react HooksReactHook
- React Hooks 梳理ReactHook
- 探React HooksReactHook
- 理解 React HooksReactHook
- Why React HooksReactHook
- React Hooks (Proposal)ReactHook
- React Hooks 指北ReactHook
- 實現 React HooksReactHook
- React Hooks總結ReactHook
- 淺談React HooksReactHook
- React Hooks 的用法ReactHook
- React Hooks 札記ReactHook
- 精讀《React Hooks》ReactHook
- 擁抱 React HooksReactHook
- React Hooks 深入系列ReactHook
- React hooks實踐ReactHook
- React Hooks的理解ReactHook
- [譯] 理解 React HooksReactHook
- React Hooks:初探·實踐ReactHook
- React Hooks 入門教程ReactHook
- 淺談 React Hooks(一)ReactHook
- React Hooks-概覽ReactHook
- React Hooks 使用詳解ReactHook
- 初探React Hooks & SSR改造ReactHook
- 淺談 React Hooks(二)ReactHook
- React-hooks 簡介ReactHook
- 使用 React Hooks 宣告 setIntervalReactHook
- react hooks初體驗ReactHook
- React Hooks 實用指南ReactHook
- React Hooks 鉤子特性ReactHook
- React — 通用hooks封裝ReactHook封裝
- React Native 的未來與React HooksReact NativeHook
- React Hooks 入門記錄ReactHook
- React Hooks入門: 基礎ReactHook
- 在Canvas中使用React HooksCanvasReactHook
- React教程:元件,Hooks和效能React元件Hook
- 快速瞭解 React Hooks 原理ReactHook