什么是hook函数
React Hook是特殊的内置函数, 可以在使用时在不编写class的情况下拥有状态(state)和副作用(side effects). 所有的hook函数都用use开头, 确保他们在组件的顶层被调用
hook函数解决了什么问题
- 简化逻辑复用
- 让代码更易理解和维护
- 为函数组件提供生命周期和创建状态
常见的的hook函数及其作用
useState
用于状态管理, 返回一个包含状态值和更新状态函数的数组, 可以更新这个数据的状态.
const [count, setCount] = useState(0);
setCount(1)
useEffect
用于执行副作用的操作, 集成了componentDidMount componentDidUpdate componentWillUnmounted三个钩子函数, 可以进行数据获取、监听事件、DOM操作等.
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// 定义一个异步函数来获取数据
const fetchData = async () => {
try {
const response = await fetch('test link');
if (!response.ok) {
throw new Error('network error');
}
const result = await response.json();
setData(result); // 更新状态
} catch (error) {
setError(error.message); // 捕获错误
} finally {
setLoading(false); // 完成加载
}
};
fetchData(); // 调用异步函数
}, []);
useRef
用于访问DOM和保存可变数据, 可以操作元素或者组件对象, 或者在渲染周期中保存可变数据但不会重新渲染.
const FocusInput = () => {
const inputRef = useRef(null); // 创建一个 ref
const handleFocus = () => {
inputRef.current.focus(); // 使用 ref 聚焦输入框
};
return (
<div>
<input
ref={inputRef} // 将 ref 赋值给输入框
type="text"
/>
<button onClick={handleFocus}>focus input</button>
</div>
);
};
useContext
用于共享状态, 子组件可以通过这个函数获取父组件传过来的context, 不需要显示的传递props.
// 创建一个 Context
const ThemeContext = createContext();
const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light'); // 默认主题为 light
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light')); // 切换主题
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
const ThemedComponent = () => {
const { theme, toggleTheme } = useContext(ThemeContext); // 使用 useContext 获取主题和切换函数
return (
<div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff', padding: '20px' }}>
<h1>Theme: {theme}</h1>
<button onClick={toggleTheme}>ChangeTheme</button>
</div>
);
};
useMemo
用于缓存计算结果, 在依赖项没有变化时, 避免重新计算.
const ExpensiveComputation = ({ number }) => {
// 一个耗时的计算
const computeFactorial = (num) => {
console.log('计算中...');
return num <= 0 ? 1 : num * computeFactorial(num - 1);
};
// 使用 useMemo 缓存计算结果
const factorial = useMemo(() => computeFactorial(number), [number]);
return (
<div>
<h2>数字: {number}</h2>
<h3>阶乘: {factorial}</h3>
</div>
);
};
const App = () => {
const [number, setNumber] = useState(1);
const [otherState, setOtherState] = useState(0);
return (
<div>
<input
type="number"
value={number}
onChange={(e) => setNumber(Number(e.target.value))}
/>
<button onClick={() => setOtherState(otherState + 1)}>更新其他状态</button>
<ExpensiveComputation number={number} />
</div>
);
};
useCallback
用于缓存函数实例, 避免在每次渲染时创建新的函数实例.
const Counter = ({ increment }) => {
console.log('Counter 组件重新渲染');
return (
<div>
<button onClick={increment}>add</button>
</div>
);
};
const App = () => {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
// 使用 useCallback 缓存 increment 函数
const increment = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<h1>当前计数: {count}</h1>
<button onClick={() => setOtherState(otherState + 1)}>更新其他状态</button>
<Counter increment={increment} />
</div>
);
};