Hooks 是什么
官方文档很简单的介绍,可以不使用 class 来实现有状态的组件
为什么要引入 Hooks
- 组件之间难以重用有状态的逻辑
虽然可以使用 render props 或者高阶组件来解决组件的重用问题,但是使用的时候我们需要把组件重构,这样会导致代码太笨重。如果使用太多的 HOC 会导致组件的层次结构很深。 https://github.com/facebook/react-devtools/pull/503,使用Hooks就可以从组件中提取有状态逻辑,以便对其进行独立测试并重用。Hooks允许我们在不更改组件层次结构的情况下重用有状态逻辑
- 逻辑复杂的组件难以开发与维护,当我们的组件需要处理多个互不相关的 localstate 时,每个生命周期函数中可能会包含着各种互不相关的逻辑在里面
Hooks 的种类
Hooks 的分类有三种,分别是
- State Hook,定义 state 和 setState 方法
- Effect Hook,通过此 Hooks 操作获取数据的方法,可以看做是
componentDidMount
,componentDidUpdate
,componentWillUnmont
的合并 - Custom Hooks,自定义 Hooks 可以将组件逻辑提取到可重用函数中,使用 use 开头
State Hook
一个简单的栗子,声明一个Counter
组件并使用useState
来声明count
状态和setCount
函数,这里使用了数组的解构
第二个参数
setCount
可以使用任意的函数名,不一定是setCount
,可以是setNumber
,setSum
...,为了规范一点使用 setCount
function Counter(props) { // 声明一个 count 状态和 setCount 函数,useState(0) 参数表示默认值 const [count, setCount] = useState(0); useEffect(() => { console.log(`mount didmount unmount and count = ${count}`); return () => { console.log('component unmount'); }; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> );}
接下来使用这个组件
class App extends Component { render() { return <div>{Counter()}</div>; }}
纳尼,报错了 Hooks can only be called inside the body of a function component. (https://fb.me/react-invalid-hook-call)
意思是 Hooks 只能在函数组件使用,不能在 class 组件使用
ReactDOM.render(<Counter name="aa" />, document.getElementById('root'));
Effect Hook
Effect Hook 也就是一个集成了componentDidMount
,componentDidUpdate
,componentWillUnmont功能的函数
上面的栗子引入了State Hook
,接下来引入 Effect Hook 到栗子 🍆 中
function Counter() { // 声明一个 count 状态和 setCount 函数,useState(0) 参数表示默认值 const [count, setCount] = useState(0); useEffect(() => { console.log(`mount didmount unmount and count = ${count}`); }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> );}
可以看到挂载和 click 的时候会触发useEffect
函数
自定义 Hook
自定义 Hook 就是以use
开头定义的 javascript 函数,比如在定义函数的时候,我们会把一些相同的逻辑封装成一个第三方函数,然后分别在其他函数使用,自定义 Hook 也是这个思想
举个栗子 🍆,我们需要在不同组件共享用户的登录状态,我们可以这样做
function useUserStatus(id) { const [isLogin, setLogin] = useState(false); useEffect(() => { setLogin(id === 1); }); return isLogin;}
function LoginBar() { const isLogin = useUserStatus(1); return <div>Login bar component {isLogin ? '已登陆' : '未登陆'}</div>;}
function App() { const isLogin = useUserStatus(1); return ( <div> App component {isLogin ? '已登陆' : '未登陆'} <LoginBar /> </div> );}
Hooks 规则
必须要在顶层使用 Hooks**,不要在循环,条件,嵌套函数使用 Hooks**
只从 React 函数调用 Hooks,不要在 js 函数调用 Hooks
总结
Hooks 其实就是以函数的思想来写类组件,不同的 Hooks 可以通过参数传递