import { useState } from 'react';function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
数组解构语法允许我们为通过调用
useState
声明的状态变量赋予不同的名称。这些名称不是useState API
的一部分。相反,React
假定如果多次调用useState
,则在每次渲染期间以相同的顺序执行。我们将回到为什么这种方法有效以及何时有用。什么是
Hook
钩子是允许从功能组件(function component)“挂钩”React状态和生命周期功能的功能。钩子在类内部不起作用 - 它们允许你在没有类的情况下使用
React
。 (我们不建议你在一夜之间重写现有组件,但如果你愿意,可以开始在新组件中使用Hook
。)
React
提供了一些像useState
这样的内置Hook
。你还可以创建自定义Hook
以在不同组件之间重用有状态行为。我们先来看看内置的Hooks
。详细说明 你可以在使用State Hook中了解更多信息。
Effect Hook
你之前可能已经从
React
组件执行数据提取,订阅或手动更改DOM
。我们将这些操作称为“副作用”(或简称为“效果”),因为它们会影响其他组件,并且在渲染过程中无法完成。
Effect Hook
中的useEffect
增加了在功能组件执行副作用的功能。它与React
类中的componentDidMount
,componentDidUpdate
和componentWillUnmount
具有相同的用途,但统一为单个API。(我们将在使用Effect Hook
时显示将useEffect
与这些方法进行比较的示例。)例如,下面的组件将在
React
更新DOM
后设置文档标题:
import { useState, useEffect } from 'react';function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); function handleStatusChange(status) { setIsOnline(status.isOnline); } // ...}Custom Hooks
有时,我们希望在组件之间重用一些有状态逻辑的部分。传统上,这个问题有两个流行的解决方案:高阶组件和渲染道具。
Custom Hooks
允许你执行这样的操作,并且无需向树中添加更多组件。在上面我们介绍了一个调用useState
和useEffect Hooks
的FriendStatus
组件来订阅朋友的在线状态。假设我们还希望在另一个组件中重用此订阅逻辑。
首先,我们将这个逻辑提取到一个名为useFriendStatus
的自定义Hook
中:import { useState, useEffect } from 'react';function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; }它将
friendID
作为参数,并返回我们的朋友是否在线。
现在我们可以从两个组件中使用它:function FriendStatus(props) { const isOnline = useFriendStatus(props.friend.id); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }function FriendListItem(props) { const isOnline = useFriendStatus(props.friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li> ); }这些组件的状态是完全独立的。钩子是重用有状态逻辑的一种方式,而不是状态本身。 事实上,每次调用
Hook
都有一个完全隔离的状态 - 所以你甚至可以在一个组件中使用相同的自定义Hook
两次。
在之前的的hook 介绍里有一段代码:
import { useState } from 'react';function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() : setCount(count + 1)}> Click me </button> </div> ); }
我们将通过将此代码与等效的类示例进行比较来开始学习Hooks
。
等价的类示例
看下面这段代码,你会觉得很熟悉
class Example extends React.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> ); } }
状态以{count:0}
开始,当用户通过调用this.setState
单击按钮时,我们会增加state.count
。我们将在整个页面中使用此类的片段。
注意 你可能想知道为什么我们在这里使用计数器而不是更现实的例子。这是为了帮助我们专注于
API
,同时我们仍在使用Hooks
迈出第一步。
Hooks和函数组件
提醒一下,React中的函数组件如下所示:
const Example = (props) : { // You can use Hooks here! return <div />; }
或者是下面这样的:
function Example(props) { // You can use Hooks here! return <div />; }
你可能以前将这些称为“无状态组件”。我们现在介绍的这些中具有使用React状态的能力,所以我们更喜欢名称function components
。
Hook
在class
内 不起 作用。但是你可以使用它们而不是编写类。
什么是Hook
我们的新示例首先从React
导入useState Hook
:
import { useState } from 'react';function Example() { // ...}
什么是Hook
? Hook
是一种特殊功能,可让你“挂钩”React
功能。例如,useState
是一个Hook
,允许你将React
状态添加到函数组件。我们稍后会学习其他的Hooks
。
我什么时候使用Hook
? 如果你编写一个函数组件并意识到你需要为它添加一些状态,那么之前你必须将它转换为一个类。但是现在,你可以在现有功能组件中使用Hook
。我们现在要做到这一点!
注意: 关于在何处可以使用
Hook
并且不能在组件中使用Hook
,有一些特殊规则。我们将在“钩子规则”中学习它们。
声明一个状态变量
在class
组件中,我们声明一个状态需要向下面这样:
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } //...}
在函数组件中,我们没有this
,所以我们不能分配或读取this.state
。相反,我们直接在组件内部调用useState Hook
:
import { useState } from 'react';function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); // ... }
调用useState有什么作用? 他声明了一个状态变量
。我们的变量叫做count
,但我们可以称之为其他任何东西,比如banana
。这是一种在函数调用之间“保留”某些值的方法 - useState
是一种使用this.state
在类中提供的完全相同功能的新方法。通常,当函数退出时变量“消失”但React
保留状态变量。
我们传递给useState
的参数是什么? useState Hook
的唯一参数是初始状态。与类不同,状态不必是对象。他可以是任何我们需要的内容,比如数字,字符串等。在我们的示例中,我们只需要一个数字来表示用户点击的次数,因此将0作为变量的初始状态。(如果我们想在状态中存储两个不同的值,我们将调用useState
两次。)
useState
返回的是什么? 它返回一对值:当前状态和更新状态的函数。这就是我们编写const [count,setCount] = useState(0)
的原因。这与类中的 this.state.count
和this.setState
类似,只不过现在它们是成对的。
现在我们知道了useState Hook
的作用,我们的例子应该更有意义
2.
l
3.
4.
k
5.
f
6.
7.