引入
Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。Hooks 在函数组件中提供了多种方式来管理状态和生命周期,让代码更简洁、可读性更强。
useState
useState 是一个 Hook,它可以让函数组件拥有状态。每个函数组件都可以通过 useState 来声明局部状态变量。这个状态变量的值可以在函数组件的多次渲染之间保持一致。
// www.javascriptcn.com code example
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>当前计数: {count}</p>
<button onClick={() => setCount(count + 1)}>点击增加</button>
</div>
);
}在这个例子中,useState 返回一个数组,第一个元素是状态变量 count,第二个元素是更新状态的函数 setCount。
useEffect
useEffect Hook 可以让你执行副作用操作,例如数据获取、订阅或手动更改 DOM。它类似于 class 组件中的 componentDidMount, componentDidUpdate 和 componentWillUnmount 方法的组合。
// www.javascriptcn.com code example
import React, { useState, useEffect } from 'react';
function ExampleWithUseEffect() {
const [count, setCount] = useState(0);
const [data, setData] = useState(null);
useEffect(() => {
document.title = `You clicked ${count} times`;
fetch('https://api.example.com/data')
.then(response => response.json())
.then(json => setData(json));
}, [count]); // 只有当 count 发生变化时,effect 才会重新运行
return (
<div>
<p>当前计数: {count}</p>
<button onClick={() => setCount(count + 1)}>点击增加</button>
<p>{data ? data.message : '加载中...'}</p>
</div>
);
}在这个例子中,useEffect 第二个参数是一个依赖数组,只有当数组中的值发生变化时,useEffect 中的回调函数才会执行。
useContext
useContext Hook 允许你在函数组件中订阅 React 的 Context。它使得你可以避免在组件树中逐层传递 props。
// www.javascriptcn.com code example
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ background: theme === 'dark' ? 'black' : 'white', color: theme === 'dark' ? 'white' : 'black' }}>切换主题</button>;
}在这个例子中,useContext Hook 让 ThemedButton 组件可以直接访问到 ThemeContext 提供的主题值,而不需要通过 props 一层层传递。
useReducer
useReducer Hook 用来处理更复杂的状态逻辑,特别是当状态更新依赖于先前状态的时候。它通常用于替代 useState。
// www.javascriptcn.com code example
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}在这个例子中,useReducer 用于管理 Counter 组件的状态逻辑。reducer 函数接收当前状态和动作对象作为参数,并返回新的状态。
自定义 Hooks
自定义 Hooks 是一种复用状态逻辑的方式。自定义 Hooks 必须以 use 开头,这可以帮助 React 识别该 Hook。
// www.javascriptcn.com code example
import { useState, useEffect } from 'react';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return '加载中...';
}
return isOnline ? '在线' : '离线';
}在这个例子中,useFriendStatus 是一个自定义 Hook,它订阅了朋友的状态变化,并在组件卸载时取消订阅。这样,我们就可以在任何组件中使用这个逻辑。
总结
Hooks 是 React 16.8 中引入的一个重要特性,它们允许你在函数组件中添加状态和其他 React 特性。通过使用 useState, useEffect, useContext, useReducer 以及自定义 Hooks,你可以写出更加简洁、可维护的代码。Hooks 使你能够在函数组件中处理复杂的逻辑,同时保持代码的清晰和可读性。