函数组件很棒,但它们仅限于通过属性来完成它们所说的。当你需要它们意识到它们的状态时,你就被迫将它们重写为类组件。
其中一个功能,目前在alpha中,预计将在React v16.7中登陆,是Hooks(https://reactjs.org/docs/hooks-intro.html)。
开始的
正如上面提到的,此功能目前在alpha中,但预计将是React的下一个点发布的一部分,因此,我们需要在添加React到我们的项目时指定一个版本。
1# Via npm
2$ npm install --save react@next react-dom@next
3
4# Or via Yarn
5$ yarn add react@next react-dom@next
什么使一个胡克?
- 必须从
使用
一词开始 *只有在函数组件内和自定义的胡克可以调用胡克,这具有保持组件逻辑精心组合的额外优惠 *只使用顶级的胡克,从未从函数组件内的条件,循环或嵌入函数内部调用胡克。
国家组成
要使用 Hooks 创建一个 stateful 函数组件,我们需要从 React 包中使用useState
初始化该状态。
此方法接受设置初始状态的参数,并返回包含当前状态和设置状态的函数的数组。
以下是状态函数组件,它会跟踪随机设置的颜色,每次按下按钮:
1import React, { useState } from "react";
2import { render } from "react-dom";
3
4function StatefulFn() {
5 const [color, setColor] = useState(false);
6
7 function onClick() {
8 const colors = [
9 "#008F68",
10 "#6DB65B",
11 "#4AAE9B",
12 "#FAE042",
13 "#EFBB35",
14 "#DFA612"
15 ];
16
17 setColor(colors[Math.floor(Math.random() * colors.length)]);
18 }
19
20 return (
21 <button onClick={onClick} style={{ backgroundColor: color }}>
22 Click to Change Button Color
23 </button>
24 );
25}
26
27const container = document.createElement("div");
28document.body.appendChild(container);
29render(<StatefulFn />, container);
由于这个原因,我们要么自己手动维护一个状态对象,要么更简单地说,只需多次拨打useState
来跟踪我们状态中的每个变量:
1const [color, setColor] = useState(false);
2const [size, setSize] = useState('medium');
3const [reptile, setReptile] = useState('alligator');
生命周期组成部分
使用函数组件的另一个缺陷是它们缺乏生命周期方法. Hooks 功能的另一个部分是useEffect
的添加,它是componentDidMount
,componentDidUpdate
和componentWillUnmount
的组合。
更简单地说,useEffect
将在初始渲染和随后的任何再渲染后发射。
如果你熟悉 React 类组件生命周期,你知道在渲染方法中放置具有副作用的代码是不好的,这就是为什么生命周期方法存在的原因。
其中一个副作用是关闭网络请求,然后以返回的值更新状态. 在下一个示例中,我将使用设置时空
来模拟一个非常缓慢的网络连接,并在我们等待时显示一个加载消息:
1import React, { useEffect, useState } from "react";
2import { render } from "react-dom";
3
4function EffectedFn() {
5 const [loading, setLoading] = useState(true);
6
7 useEffect(() => {
8 setTimeout(() => {
9 setLoading(false);
10 }, 1000 * 10);
11 });
12
13 return (
14 <div>
15 {loading && <span>Loading...</span>}
16 {!loading && <span>All Done!</span>}
17 </div>
18 );
19}
20
21const container = document.createElement("div");
22document.body.appendChild(container);
23render(<EffectedFn />, container);
关于useEffect
的一点很酷的是,它不会阻止浏览器以componentDidMount
和componentDidUpdate
的方式更新屏幕。
为了进一步提高性能,特别是当您使用多个状态变量时,您可以说useEffect
仅在某个值发生变化时启动:
1useEffect(() => {
2 setTimeout(() => {
3 setLoading(false);
4 }, 1000 * 10);
5}, [loading]);
但我不想使用Hooks!
關於Hooks的真正好處是,如果你不想要使用它們,你不必使用它們,如果你熱衷於使用班級,你可以繼續使用卡車。
Hooks 是 100% 向后兼容的,所以没有必要冲浪来更新任何现有代码. 类不会去任何地方,如果/当你准备开始使用 Hooks,只要你在支持它的 React 版本,你可以这样做。
结论
个人来说,当我需要状态和生命周期支持时,我已经厌倦了输送功能,所以对我来说,胡子是一个非常受欢迎的补充。
此外,它是非常容易创建自己的钩子或使用由更大的React社区开发的钩子。 已经有 可用的钩子的集合正在出现 左和 右。
如果你像我一样,今天已经准备好开始使用Hooks,并且想看到本文中的代码在行动中,请转到CodeSandbox(https://codesandbox.io/s/xrj5v6py1p)。