导读
- Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性,编写具有 Hook 的函数组件对比以前的 class 组件来说,其好处有以下几点:
1 . 不再有生命周期函数
2 . 不再有 this 指向
3 . 函数式编程
4 . 不用引入额外的状态管理
例子:
- useState(存储状态和改变状态的函数):
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 钩子功能的副作用函数):
import React, { useState, useEffect } from "react";
import { BrowserRouter, Route, Link } from "react-router-dom";
const Home = () => {
useEffect(() => {
console.log(`useEffect => 来了老弟 - Home`); // 只要组件加载或更新都会执行
return () => {
console.log(`Home - 走了`);
}; // 用来清除本次副作用,当组件执行下一次副作用函数时会执行
}, []);
// useEffect第二个参数传空值代表当该组件卸载(ComponentWillUnMount)时才执行清除副作用函数(return的函数)
// useEffect第二个参数不为空值,则对应当依赖值改变时才执行副作用函数,清除副作用函数执行机制同上
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!`); // 每次渲染/更新都会执行
});
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 第二个参数设为空值时:
useEffect1
useEffect2
当不设置 useEffect 第二个参数时(默认只要组件有变化就会执行解绑函数):
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 第二个参数为状态的初始值,第三个参数是自定义函数
return (
<>
<h2>现在的分数是{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 包裹后的组件,也就是使用传递过来的状态
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>
);
};
总结
- 个人的话目前使用还是不太熟悉,但是能理清逻辑调用,至于实践上真正优秀的地方暂时还没什么感觉,全局 useReducer 同理使用,对应一个全局 createContext,大家可以去 React 官网查阅相关用法,这里只供个人加深印象而作 ^ _ ^.