Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。React Hook使得函数组件的功能得到了极大的增强
以下是使用React Hook和类组件同时实现计数器功能的示例:
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
handleClick() {
this.setState({
count: this.state.count + 1
});
}
render() {
return (
You clicked {this.state.count} times
);
}
}
export default Counter;
可以看出使用类组件需要手动维护状态和生命周期方法,这使得代码更加冗长,并且容易出错。
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
You clicked {count} times
);
}
export default Counter;
而React Hook的代码要比使用类组件的代码更加简洁明了。使用useState和useEffect Hook可以让我们在函数组件中轻松地管理状态和效果。此外,使用React Hook还可以让我们更好地复用代码。由于Hook是一种独立的函数,可以在任何函数组件中使用,因此我们可以将一些复杂的逻辑封装在一个自定义的Hook中,然后在多个组件中共享该Hook。
在 React 中,状态(State)是管理组件内部数据的一种机制。使用状态可以保存组件内部数据,使得组件可以根据数据的变化实现不同的渲染效果,hook中 useState 就是用来定义和更新组件状态的 。
useState Hook 的基本用法
在函数组件中使用 useState Hook,需要先调用 useState 函数,该函数接受一个初始状态值作为参数,并返回一个数组,该数组包含两个值:
(1)状态值:即初始状态值或者最新的状态值。
(2)更新状态的函数:该函数可以用来更新组件状态。
上面的计数器例子中useState(0) 表示初始化状态为 0,同时返回一个长度为 2 的数组。数组中的第一个元素 count 表示当前状态值,第二个元素 setCount 是一个函数,用于更新状态值。通过调用 setCount 函数,我们可以更新状态值,并且在组件重新渲染时显示新的状态值。
useState 可以理解为是组件内全局变量,可以再本组件内任何地方,获取和更新值,使用起来非常灵活
在 React 中,组件可以随着时间和用户操作的变化而不断地更新自己的状态和显示内容。但有时候,我们需要在组件更新后执行一些额外的操作,比如获取远程数据、添加事件监听器等。在这种情况下,我们可以使用 useEffect Hook 来处理组件的副作用。
useEffect Hook 的基本用法
在函数组件中使用 useEffect Hook,需要先调用 useEffect 函数,该函数接受两个参数:
(1)副作用函数:用于执行组件的副作用操作,可以是一个异步函数或者同步函数。
(2)依赖项数组:一个可选的数组,用于指定副作用函数的依赖项,只有依赖项发生变化时,才会重新执行副作用函数。
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [users, setUsers] = useState([]);
const [count, setCount] = useState(0);
useEffect(() => {
async function fetchData() {
const result = await axios('www.baidu.com');
setUsers(result.data);
}
fetchData();
}, []);
useEffect(() => {
console.log(`You clicked ${count} times`);
}, [count]);
function handleClick() {
setCount(count + 1);
}
return (
{users.map(user => (
- {user.name}
))}
);
}
在上面的代码中,我们使用了两个 useEffect Hook,分别定义了获取用户数据和更新计数器的副作用函数。第一个 useEffect Hook 依赖项数组为空,表示只在组件首次渲染时执行一次。第二个 useEffect Hook 依赖项数组为 [count],表示只在计数器发生变化时执行。
在 React 中,我们通常使用状态(State)来管理组件内部的数据,但有时候,我们需要在组件中保存一些不需要触发重新渲染的数据或引用,比如获取 DOM 元素、缓存数据等。在这种情况下,我们可以使用 useRef Hook 来处理这些数据或引用。
useRef Hook 的基本用法
在函数组件中使用 useRef Hook,需要先调用 useRef 函数,该函数接受一个初始值作为参数,并返回一个可变的 ref 对象,该对象包含一个 current 属性,指向传入的初始值。
例如,下面的代码我们使用了 useRef Hook 来创建一个 timerRef 对象,用于保存定时器的引用。在 useEffect Hook 中,我们使用 timerRef.current 设置定时器,并在组件销毁时清除定时器。在 handleClick 函数中,我们可以通过 clearInterval(timerRef.current) 清除定时器
import React, { useState, useEffect, useRef } from 'react';
function App() {
const [count, setCount] = useState(0);
const timerRef = useRef(null);
useEffect(() => {
timerRef.current = setInterval(() => {
setCount(count => count + 1);
}, 1000);
return () => clearInterval(timerRef.current);
}, []);
function handleClick() {
clearInterval(timerRef.current);
}
return (
You clicked {count} times
);
}
Hook 本质就是 JavaScript 函数,但是在无论使用哪几个hook使用它时都需要遵循一些规则
只能在函数组件中使用:React Hook 只能在函数组件的顶层作用域中使用,不能在类组件中使用。
只能在 React 函数组件中使用 Hook:React Hook 只能在 React 函数组件中使用,不能在普通的 JavaScript 函数中使用。
Hook 的调用顺序必须相同:在同一个组件中,Hook 的调用顺序必须保持一致。如果 Hook 的调用顺序发生变化,可能会导致组件状态的不稳定。
只能在顶层使用 Hook:React Hook 只能在函数组件的顶层作用域中使用,不能在条件语句、循环语句或嵌套函数中使用。
自定义 Hook 是一种代码复用的方式,可以将一些重复的逻辑或状态抽象出来,以 Hook 的形式提供给其他组件使用。自定义 Hook 的命名约定是使用 "use" 开头,这样 React 就可以自动检测到这是一个 Hook 进行相关处理。
创建自定义 Hook 的样例代码如下:
import { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
function handleResize() {
setWidth(window.innerWidth);
}
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return width;
}
export default useWindowWidth;
在其他组件中使用自定义 Hook 时,只需要导入并调用即可。
import React from 'react';
import useWindowWidth from './useWindowWidth';
function App() {
const width = useWindowWidth();
return (
Window width: {width}px
);
}
export default App;