前言
在做 React 项目时我们可以选择使用 class 类组件 或者 function 函数组件,在 React 16.8 之前,使用函数组件是为一个无状态的组件通常只做为展示,渲染组件工作。在 React 16.8 里,react 新增了一个特性------ Hook,能让我们在不使用 class 的情况下,也可以使用 state 以及 React 的其它特性。
介绍
Hooks 其实就是一个 Javascript 的函数。在 React 里,它就给我们提供了几个 hook 供我们使用,像 useState
、userContext
、useEffect
等等,在 React 里经常使用的一些库如 react-router-dom ,就有着 useNavigate
、 useRoutes
等,去起到切换路由、使用路由表等工作,能够帮我们处理一些事务,所以去做 react 项目时,它允许在函数式组件中使用状态和其他 React 特性。Hooks 旨在解决在类组件中使用复杂逻辑、共享状态和处理副作用时的一些问题,使得函数式组件具有更多的能力和灵活性。
使用
让我们先了解下 React 给我们提供比较常用的 hook,能够帮我们做到哪些事情
useState
useState 用于在函数组件里调用它来满足给组件添加一些内部state(状态)。
从 react 中导入 useState 使用,使用 useState 可以传入初始值,执行返回一个有状态值和一个函数来更新它。
在后续重新渲染期间,useState 返回的第一个值将始终是应用更新后的最新状态,拿到最新值才进行最终的渲染,提高性能。
js
import React, { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(1);
return (
<div>
{/* 点击按钮 +1 */}
<h1>当前 count 值:{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
useEffect
useEffect (副作用钩子) 用于在 React 组件需要在渲染后执行某些操作,因为 useEffect 保证是在执行 DOM 更新完成之后才调用它,在第一次渲染之后和每次更新之后都会去执行,可以在里面获取到最新的 DOM。
js
import React, { useState, useEffect } from 'react';
export default function Counter() {
const [count, setCount] = useState(1);
// 相当于 componentDidMount 和 componentDidUpdate 组件生命钩子函数
useEffect(() => {
console.log(`当前最新 count 值 为 ${count} `)
});
// 也可以给予第二个参数,用于监听某个 state 值
useEffect(() => {
console.log(`当前最新 count 值 为 ${count} `)
}, [count]); // 仅在 count 更改时更新
return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
useContext
userContext 它接受一个上下文对象,并返回该上下文的当前值,可以帮助我们跨越组件层级直接传递变量,不需要手动传值给每个子组件,就可以做到实现数据共享。
js
import { useState, createContext, useContext } from 'react';
const CountContext = createContext(1)
function Home() {
// 定义要传递的值
const [ count, setCount] = useState(1)
return (
<div>
<CountContext.Provider value={ count }>
<Header />
</CountContext.Provider>
<p>Hello, home! 当前值为 { count }</p>
<button onClick={() => setCount(count + 1)}>{'点击+1'}</button>
</div>
);
}
const Header = ()=> {
// 接收上面定义的上下文对象
const count = useContext(CountContext)
return (
<div>
// 该 count 值随 Home 组件的点击事件变化
<p>Hello, Header! 当前 count 值为 { count }</p>
</div>
);
}
export default Home
除去以上三种 Hooks ,React还提供了其他Hooks函数,如 useReducer
、useCallback
、useMemo
、useRef
等,以满足不同的需求和场景。
那么我们想要创建自己的 hook 要怎么做呢?
自定义 hook
在自定义 Hooks 中通常以 use
开头,像 useState、useContext等都是这样的。
这里设置一个 count 值加 1 和重置为初始值,定义好后就可以在组件中导入使用 useCount 函数。
js
import { useState } from "react";
function useCount(initialState) {
const [count, setCount] = useState(initialState);
const handleAdd = () => {
setCount(count + 1);
};
const resetCount = () => {
setCount(initialState);
};
return [count, handleAdd, resetCount];
}
export default useCount;
js
// 导入使用自定义 Hooks
import useCount from './useCount';
function Home() {
const [ count, handleAdd, resetCount] = useCount(0)
return (
<div>
<p>Hello, home! 当前值为 { count }</p>
<button onClick={handleAdd}>点击+1</button>
<button onClick={resetCount}>重置</button>
</div>
);
}
export default Home
总结
- 有着更好的逻辑和状态的复用,通过自定义 Hooks ,将一些重复使用的逻辑和状态封装称为一个函数,可以在不同的组件中使用该函数,去共享,避免组件之间状态和逻辑重复编写的问题
- 可以灵活的去设计组件,在函数式组件中使用状态、副作用和 React 的其它特性,使代码更加清晰
- 使用 Hooks,能极大简化代码,使逻辑清晰明了,提高代码的可读性和可维护性