时隔一年半之久再次重新学习 React,好多都还是原来的样子,这次我要重新开启 React 的大门,希望各位小伙伴可以一起讨论学习呦~
前言
今天我们开启第四个专题:函数组件中 React Hooks 详解与实践。 在 16.8 版本之后的 React 发布了新特性 Hooks。 本篇文章主要对该新特性进行了详细讲解,并对一些常用的 Hooks 进行代码演示,希望可以对需要的小伙伴提供一些帮助。
一、什么是 Hooks ?
Hooks 是 React v16.7.0-alpha 中加入的新特性。它可以让你在 class 以外使用 state 和其他 React 特性。 这个 API 是 React 的未来,各位有必要深入理解。
Hook 这个单词的意思是"钩子"。
React Hooks 的意思是:组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。 React Hooks 就是那些钩子。
当我们需要什么功能,就使用什么钩子。React 默认提供了一些常用钩子,你也可以封装自己的钩子。
所有的钩子都是为函数引入外部功能,所以 React 约定,钩子一律使用 use 前缀命名,便于识别。你要使用 xxx 功能,钩子就命名为 usexxx。
二、Hooks 怎么用 ?
比如:useState 就是一个 Hook,可以在我们不使用 class 组件的情况下,拥有自身的 state ,并且可以通过修改 state 来控制 UI 的展示。
import React, { useState } from 'react';
function Foo() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Foo;
是不是在函数式组件里使用 Hooks 很方便?那我们在对比一下实现同样的功能,在类组件中使用呢。
import React, { Component } from "react";
export default class Foo extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
这个类组件仅仅是实现了一个点击累加的功能,但可以看到,它的代码已经很"重"了。真实的 React App 由多个类按照层级,一层层构成,复杂度成倍增长。再加入 Redux,就变得更复杂。
三、Hooks 有哪些 ?
常用的几个: useState() useEffect() useReducer() useContext() 简单了解: useCallback() useMemo() useRef() useLayoutEffect() useImperativeHandle()
1、useState
-
语法 const [state, setState] = useState(initialState)
-
优化方案 在创建初始状态是比较昂贵的,所以我们可以在使用 useState API 时,传入一个函数,就可以避免重新创建忽略的初始状态。
const [rows, setRows] = useState(() => createRows(props.count));
2、useEffect
之前很多具有副作用的操作,例如网络请求,修改 UI 等,一般都是在 class 组件的 componentDidMount 或者 componentDidUpdate 等生命周期中进行操作。而在函数组件中是没有这些生命周期的概念的,只能 return 想要渲染的元素。 但是现在,在函数组件中也有执行副作用操作的地方了,就是使用 useEffect 函数。
-
语法 useEffect(() => { doSomething });
-
注意
虽然传递 [] 更接近熟悉的 componentDidMount 和 componentWillUnmount 执行规则,但我们建议不要将它作为一种习惯,因为它经常会导致错误。
-
优化方案 useEffect 的第二个参数是一个数组,里面放入在 useEffect 使用到的 state 值,可以用作优化,只有当数组中 state 值发生变化时,才会执行这个 useEffect 。 useEffect(() => {
document.title = `You clicked ${count} times`;
}, [ count ]);
Tip:如果想模拟 class 组件的行为,只在 componetDidMount 时执行副作用,在 componentDidUpdate 时不执行,那么 useEffect 的第二个参数传一个 [] 即可。(但是不建议这么做,可能会由于疏漏出现错误)
3、useReducer
-
语法 const [state, dispatch] = useReducer(reducer, initialArg, init);
useState 的替代方案。 接受类型为 (state, action) => newState 的reducer ,并返回与 dispatch 方法配对的当前状态。 当你涉及多个子值的复杂 state (状态) 逻辑时,useReducer 通常优于 useState 。 -
优化:延迟初始化 还可以惰性地创建初始状态。为此,你可以将init函数作为第三个参数传递。初始状态将设置为 init(initialArg) 。 -
与 useState 的区别
- 当
state 状态值结构比较复杂时,使用 useReducer 更有优势。 - 使用
useState 获取的 setState 方法更新数据时是异步的;而使用 useReducer 获取的 dispatch 方法更新数据是同步的。
4、useContext
5、
其他后面几个 Hooks 的用法我将在最近进行补充,感谢大家支持!
四、自定义 Hooks ?
后续待补充…
五、使用 Hooks 需要注意什么?
- 不要从常规 JavaScript 函数调用 Hooks;
- 不要在循环,条件或嵌套函数中调用 Hooks;
- 必须在组件的顶层调用 Hooks;
- 可以从 React 功能组件调用 Hooks;
- 可以从自定义 Hooks 中调用 Hooks;
- 自定义 Hooks 必须使用 use 开头,这是一种约定;
希望以上内容可以帮助到大家。我也是重新开始学习 React,欢迎大家一起讨论学习,最后不要忘记一键三连哦~
如果有什么不对或不严谨的地方,欢迎大家能提出宝贵的意见,十分感谢。
各位 加油!
参考文档: React 官网 React Hooks FAQ
|