導讀
- Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性,編寫具有 Hook 的函數(shù)組件對比以前的 class 組件來說,其好處有以下幾點:
1 . 不再有生命周期函數(shù)
2 . 不再有 this 指向
3 . 函數(shù)式編程
4 . 不用引入額外的狀態(tài)管理
例子:
- useState(存儲狀態(tài)和改變狀態(tài)的函數(shù)):
import React, { useState } from "react";
const App = () => {
const [count, setCount] = useState(0); // useState中的為count初始值
return (
<div className="App">
<p>You clicked {count} times!</p>
<button onClick={() => setCount(count + 1)}>提交</button>
</div>
);
};
export default App;
- useEffect(可以理解為具有以前 class 的 ComponentDidMount,ComponentDidUpdate,ComponentWillUnMount 鉤子功能的副作用函數(shù)):
import React, { useState, useEffect } from "react";
import { BrowserRouter, Route, Link } from "react-router-dom";
const Home = () => {
useEffect(() => {
console.log(`useEffect => 來了老弟 - Home`); // 只要組件加載或更新都會執(zhí)行
return () => {
console.log(`Home - 走了`);
}; // 用來清除本次副作用,當組件執(zhí)行下一次副作用函數(shù)時會執(zhí)行
}, []);
// useEffect第二個參數(shù)傳空值代表當該組件卸載(ComponentWillUnMount)時才執(zhí)行清除副作用函數(shù)(return的函數(shù))
// useEffect第二個參數(shù)不為空值,則對應當依賴值改變時才執(zhí)行副作用函數(shù),清除副作用函數(shù)執(zhí)行機制同上
return <h2>Vern.com</h2>;
};
const List = () => {
useEffect(() => {
console.log(`useEffect => 來了老弟 - PageList`);
return () => {
console.log(`PageList - 走了`);
};
}, []);
return <h2>ListPage</h2>;
};
const Counter = () => {
let count = useContext(CountContext);
return <h2>{count}</h2>;
};
const App = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`useEffect => you clicked ${count} times!`); // 每次渲染/更新都會執(zhí)行
});
return (
<div className="App">
<p>You clicked {count} times!</p>
<button onClick={() => setCount(count + 1)}>提交</button>
<BrowserRouter>
<ul>
<li>
<Link to="/">首頁</Link>
</li>
<li>
<Link to="/list">列表</Link>
</li>
</ul>
<Route path="/" exact component={Home} />
<Route path="/list" exact component={List} />
</BrowserRouter>
</div>
);
};
export default App;
當 useEffect 第二個參數(shù)設為空值時:
useEffect1
useEffect2
當不設置 useEffect 第二個參數(shù)時(默認只要組件有變化就會執(zhí)行解綁函數(shù)):
image.png
- useContext(用于父子組件傳值):
import React, { useState, createContext, useContext } from "react";
const CountContext = createContext();
const Counter = () => {
let count = useContext(CountContext);
return <h2>{count}</h2>;
};
const App = () => {
const [count, setCount] = useState(0);
return (
<div className="App">
<p>You clicked {count} times!</p>
<button onClick={() => setCount(count + 1)}>提交</button>
<CountContext.Provider value={count}>
<Counter />
</CountContext.Provider>
</div>
);
};
export default App;
- useReducer(類似 Redux 的 reducer):
import React, { useReducer } from "react";
const init = initialCount => {
return { count: initialCount };
};
const countReducer = (state, action) => {
switch (action.type) {
case "add":
return { count: state.count + 1 };
case "sub":
return { count: state.count - 1 };
case "reset":
return init(action.payload);
default:
throw new Error();
}
};
const App = () => {
const [state, dispatch] = useReducer(countReducer, 0, init);
// useReducer 第二個參數(shù)為狀態(tài)的初始值,第三個參數(shù)是自定義函數(shù)
return (
<>
<h2>現(xiàn)在的分數(shù)是{state.count}分</h2>
<button onClick={() => dispatch({ type: "reset", payload: 0 })}>
Reset
</button>
<button onClick={() => dispatch({ type: "add" })}>+</button>
<button onClick={() => dispatch({ type: "sub" })}>-</button>
</>
);
};
export default App;
-
useContext 和 useReducer 做類似 Redux 的功能:
默認紅色
點擊變藍
點擊變黃
// 入口文件
import React from "react";
import Body from "./views/home/body";
import Header from "./views/home/header";
import { Color } from './views/home/hooks';
// 類似 Hoc 導出通過 ColorContext 包裹后的組件,也就是使用傳遞過來的狀態(tài)
const App = () => {
return (
<>
<Color>
<Header />
<Body />
</Color>
</>
);
};
export default App;
import React, { useContext } from "react";
import { ColorContext } from "./hooks";
const Header = () => {
const {home} = useContext(ColorContext);
return <p style={{color: home.color}}>我是一段變色文字</p>;
};
export default Header;
import React, { useContext } from "react";
import { ColorContext, CHNAGE_COLOR } from "./hooks";
const Body = () => {
const { dispatch } = useContext(ColorContext);
return (
<>
<button onClick={() => dispatch({type: CHNAGE_COLOR, color: 'blue'})}>藍色</button>
<button onClick={() => dispatch({type: CHNAGE_COLOR, color: 'yellow'})}>黃色</button>
</>
);
};
export default Body;
import React, { createContext, useReducer } from "react";
export const ColorContext = createContext({});
export const CHNAGE_COLOR = "change_color";
const reducer = (state, action) => {
switch (action.type) {
case CHNAGE_COLOR:
return {
...state,
color: action.color
};
default:
return state;
}
};
export const Color = props => {
const [home, dispatch] = useReducer(reducer, { color: "red" });
return (
<ColorContext.Provider value={{ home, dispatch }}>
{props.children}
</ColorContext.Provider>
);
};
總結
- 個人的話目前使用還是不太熟悉,但是能理清邏輯調用,至于實踐上真正優(yōu)秀的地方暫時還沒什么感覺,全局 useReducer 同理使用,對應一個全局 createContext,大家可以去 React 官網查閱相關用法,這里只供個人加深印象而作 ^ _ ^.